Why do 'and' & 'or' return operands in Python?
我正在经历LPTHW,我遇到了一些我无法理解的东西。什么时候你想要你的布尔
我运行了以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | >>> False and 1 False >>> True and 1 1 >>> 1 and False False >>> 1 and True True >>> True and 121 121 >>> False or 1 1 >>> False or 112 112 >>> False or"Khadijah" 'Khadijah' >>> True and 'Khadijah' 'Khadijah' >>> False or 'b' 'b' >>> b = (1, 2,"K") >>> b (1, 2, 'K') >>> False or b (1, 2, 'K') >>> |
请帮我理解这里发生的事情。
根据文档:http://docs.python.org/2/library/stdtypes.html
除非另有说明,否则具有布尔结果的操作和内置函数始终返回
根据LPTHW:http://learnpythonthehardway.org/book/ex28.html
为什么
Python和许多类似的语言将其中一个操作数返回到它们的布尔表达式而不仅仅是True或False。这意味着如果你做了False而你得到了第一个操作数(False),但是如果你做了True而得到了你得到第二个(1)。玩这个有点。
我认为你对文档所说的内容感到困惑。看看这两个文档部分:真值测试和布尔运算符。引用第一节的最后一段:
Operations and built-in functions that have a Boolean result always return 0 or False for false and 1 or True for true, unless otherwise stated. (Important exception: the Boolean operations or and and always return one of their operands.)
正如您所看到的,您对操作和内置函数是正确的,但是请参阅重要的异常部分,可以说布尔运算符将返回其中一个操作数。
现在,他们可以返回的内容几乎不取决于运营商的短路逻辑。对于
对于
你的问题中有很多例子,我们来分析一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | >>> False and 1 # return false (short circuited at first falsey value) False >>> True and 1 # return 1 (never short circuited and return the last truthy value) 1 >>> 1 and False # return false (short circuited at first falsey value, in this case the last operand) False >>> 1 and True # return True (never short circuited and return the last truthy value) True >>> True and 121 # return 121 (never short circuited and return the last truthy value) 121 >>> False or 1 # return 1 (since the first operand was falsey, or kept looking for a first truthy value which happened to be the last operator) 1 >>> False or 112 # return 112 for same reason as above 112 >>> False or"Khadijah" # return"Khadijah" for same reason as above 'Khadijah' >>> True and 'Khadijah' # return"Khadijah" because same reason as second example 'Khadijah' |
我认为这应该说明一点。为了帮助您进一步了解其有用的原因,请考虑以下示例:
您有一个随机生成名称的函数
1 2 3 4 | import random def generate_name(): return random.choice(['John', 'Carl', 'Tiffany']) |
并且你有一个变量,你不知道它是否已经分配了一个名称而不是这样做:
1 2 | if var is None: var = generate_name() |
你可以做oneliner:
1 | var = var or generate_name() |
由于
最后但并非最不重要的是,这与静态类型,鸭类型,动态,解释,编译,无论何种语言无关。它只是一种语言功能,可能会派上用场,这很常见,因为我能想到的几乎所有编程语言都提供此功能。
希望这可以帮助!
这与Python中实现短路效果的方式有关。
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>> import dis >>> >>> dis.dis(lambda : True and 0) 1 0 LOAD_CONST 2 (True) 3 JUMP_IF_FALSE_OR_POP 9 6 LOAD_CONST 1 (0) >> 9 RETURN_VALUE >>> >>> True and 0 0 >>> 0 and True 0 >>> |
sm to:
1 2 3 4 | def exec_and(obj1, obj2): if bool(obj1) != False: return obj2 return obj1 |
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>> dis.dis(lambda : 0 or False) 1 0 LOAD_CONST 1 (0) 3 JUMP_IF_TRUE_OR_POP 9 6 LOAD_CONST 2 (False) >> 9 RETURN_VALUE >>> >>> True or 0 True >>> 1 or False 1 >>> False or 1 1 >>> |
sm to:
1 2 3 4 | def exec_or(obj1, obj2): if bool(obj1) != True: return obj2 return obj1 |
有人希望
1 2 3 4 5 6 7 8 | def foo(self): # currentfoo might be None, in which case return the default return self.currentfoo or self.defaultfoo() def foobar(self): # foo() might return None, in which case return None foo = self.foo() return foo and foo.bar() |
你当然可以质疑这些习语的价值,特别是如果你不习惯这些习语。始终可以使用显式
作为反对他们的观点,他们怀疑是否有可能并且有意识地考虑了所有虚假价值,或仅仅是评论中提到的那些(不允许其他虚假值)。但是,对于使用可能不是
考虑以下用例:
1 | element = dict.has_key('foo') and dict['foo'] |
将
1 | print element or 'Not found!' |
将这两行放在一起将打印出
这可以简化为
1 | print dict.has_key('foo') and str(dict['foo']) or 'Not found!' |
并且在功能上等同于:
1 2 3 4 | if dict.has_key('foo'): print dict['foo'] else: print 'Not found!' |