2

operator模块可以在以下情况下轻松避免不必要的函数和 lambda:

import operator

def mytest(op, list1, list2):
    ok = [op(i1, i2) for i1, i2 in zip(list1, list2)]
    return all(ok)

mytest(operator.eq, [1, 2, 3], [1, 2, 3])         # True
mytest(operator.add, [-1, 2, -3], [1, -2, 33])    # False

好吧,现在我需要做,但令我惊讶的是,我在操作员模块中i1 and i2找不到!and这同样适用于or!我知道,andis 不完全是operator,它是一个keyword,但是和 evennot一起,都是关键字,并且都包含在内。isdel

那么故事是什么?为什么他们失踪了?

4

4 回答 4

9

因为您不能将布尔运算符转换为 python 函数。函数总是计算它们的参数,而布尔运算符则不会。添加andandor到操作符模块还需要添加一种特殊类型的函数(如 lisp“宏”)来按需评估它们的参数。显然,这不是 Python 设计者想要的。考虑:

if obj is not None and obj.is_valid():
    ....

你不能把它写成函数形式。像这样的尝试

  if operator.xyz(obj is not None, obj.is_valid()) 

如果objis 实际上会失败None

于 2013-10-04T16:46:08.280 回答
3

您可以自己编写这些,但您需要为第二个参数传递一个函数(例如 lambda),以防止在调用时对其进行评估,假设通常的短路行为对您很重要。

def func_or(val1, fval2):
    return val1 or fval2()

def func_and(val1, fval2):
    return val1 and fval2()

用法:

func_or(False, lambda: True)
func_and(True, lambda: False)
于 2013-10-04T17:49:21.687 回答
1

没有的原因operator.and是 thatand是一个关键字,所以那将是一个SyntaxError.

正如 tgh435 解释的那样,没有重命名and函数的原因operator是它会产生误导:函数调用总是评估其操作数,但and运算符不会。(这也是其他一致且简单的规则的例外。)


在您的情况下,您似乎根本不关心短路,因此可以轻松构建自己的版本:

def and_(a, b):
    return a and b

或者,如果您只使用一次,甚至是内联:

mytest(lambda a, b: a and b, [-1, 2, -3], [1, -2, 33])

在某些情况下,值得一看all(and, for or, any)。它被有效地短路and扩展为任意操作数。当然,它具有与operator函数不同的 API,采用单个可迭代的操作数而不是两个单独的操作数。而且它的短路方式也不同;它只是停止迭代可迭代对象,这仅在您进行设置时才有帮助,因此可迭代对象仅根据需要评估事物。因此,它通常不能用作替代品——但如果您稍微重构一下代码,它有时还是可以使用的。

于 2013-10-04T18:08:15.723 回答
0

Pythonandor语法不能直接映射到函数。这些语法是惰性求值的:如果表达式左侧部分的结果允许知道整个表达式的值,则跳过右侧部分。由于它们引入了流控制,因此它们的行为无法使用操作符来重现。为了减少混淆,python 选择干脆不提供这些方法。

georg 举了一个and懒惰很重要的例子:

 if obj is not None and obj.is_valid():
     ...

现在,如果您不需要惰性评估,可以使用 abarnert 的答案实现:

def and_(a, b):
    return a and b

def or_(a, b):
    return a or b

用法:

>>> or_(False, True)
>>> and_(True, False)

如果需要惰性求值,可以使用 kindall 的 answer 实现:

def func_or(val1, fval2):
    return val1 or fval2()

def func_and(val1, fval2):
    return val1 and fval2()

用法:

>>> func_or(False, lambda: True)
>>> func_and(True, lambda: False)

注意:如评论中所述,函数operator.and_operator.or_对应于位运算符&|。请参阅:https ://docs.python.org/3/library/operator.html#mapping-operators-to-functions

请注意,名称operators.andoperators.or未使用:andor是 Python 关键字,因此会出现语法错误。

于 2018-05-25T12:43:54.483 回答