Python中实现 (a and b or c) in xx 这种逻辑最简洁的方式是怎样

Original 2016-10-29 15:40:16 1023
abstract:判断 a 和 b 都在 xx里面 ,或者 c 在 xx 里面当然实际可能不止 3 个元素参与判断。怎样用简洁通用的代码实现这个逻辑?直接 按照题目上那样写虽然不报错,但是语义却完全不同In [177]: print (1 and 2) in [1,1,3]FalseIn [178]: print 1 and 22In [179]: print (1 and 2) in [2,3]True这个 (a

判断 a 和 b 都在 xx里面 ,或者 c 在 xx 里面
当然实际可能不止 3 个元素参与判断。
怎样用简洁通用的代码实现这个逻辑?


直接 按照题目上那样写虽然不报错,但是语义却完全不同
In [177]: print (1 and 2) in [1,1,3]
False
In [178]: print 1 and 2
2
In [179]: print (1 and 2) in [2,3]
True

这个 (a and b or c) in cc 一眼看上去类型不太对,先让我们把它写的更加 explicit 一些:

in_(or_(and_(contains(a), contains(b)), contains(c), cc)

可以看出,如果上述式子的类型是 Bool,而且 forsome x. a, b, c :: x; cc :: Set x; contains :: x -> Set x -> Bool,那么一个合理的类型推断是 and_, or_ :: (x -> Bool) -> (x -> Bool) -> x -> Bool; in_ :: forall x. x -> x。

正如 F91 所说,类型清楚之后,剩下的就是填空了。我们先用 Haskell 写一遍:

contains x = foldr combine False
  where
    combine x' r = x' == x || r-- Control.Concatenative-- 也可以写成 bi f g h = h <$> f <*> gbi f g h x = f x `h` g xand_ f g = bi f g (&&)or_ f g = bi f g (||)main = print x
  where
    x = (contains 1 `and_` contains 2 `or_` contains 3) [1, 3, 5]

写成 Python 就是

import operatordef contains(x):
    def call(xs):
        return x in xs
    return calldef bi(f, g, h):
    def call(x):
        return h(f(x), g(x))
    return calldef and_(f, g):
    return bi(f, g, operator.and_)def or_(f, g):
    return bi(f, g, operator.or_)print(or_(and_(contains(1), contains(2)), contains(3))([1, 3, 5]))


Release Notes

Popular Entries