出于某种原因,这个功能使我感到困惑:
def protocol(port):
return port == "443" and "https://" or "http://"
有人可以解释幕后发生的事情的顺序,使其按照它的方式工作。
直到我尝试它才明白这一点:
A)
def protocol(port):
if port == "443":
if bool("https://"):
return True
elif bool("http://"):
return True
return False
或B)
def protocol(port):
if port == "443":
return True + "https://"
else:
return True + "http://"
这是Python中的某种特殊情况,还是我完全误解了语句的工作原理?
答案 0 :(得分:24)
这是一个古老的习语;插入括号以显示优先级,
(port == "443" and "https://") or "http://"
x and y
如果y
真实,则返回x
,x
如果x
是假的,则返回a or b
; a
,反之亦然,如果它是真的,则返回b
,否则port == "443"
。
因此,如果and
为真,则返回"https://"
的RHS,即and
。否则,or
为false,因此"https://" if port == "443" else "http://"
开始播放并返回“”http://“,其 RHS。
在现代Python中,更好的方法是翻译这个古老的习语:
{{1}}
答案 1 :(得分:8)
and
返回右操作数。如果左边为假,则or
返回右操作数。否则它们都返回左操作数。他们被称为合并。
答案 2 :(得分:5)
C and X or Y
是Python用户长期尝试代理C ? X : Y
在大多数情况下,如果X
是False
,除了 - 这导致了Python代码中的许多错误,因此Python FAQ ,你会发现更正确的解决方案是(C and [X] or [Y])[0]
,因为具有单个元素的列表,无论其评估的布尔值如何,总是True
!例如:[None]
为True
,但None
不是。上面的OP示例有效,因为表示X
的字符串不为空。
但是,所有这些在Python 2.5中都有所改变,当三元或条件运算符添加到语言中时,允许您使用此处其他帖子中所述的清除X if C else Y
。如果您看到使用较旧格式的代码,那是因为用户已经是一位长期没有采用新语法的Python程序员,他们剪切了其他旧代码,或者他们的雇主仍在使用2.4.x(或早期版本)等。
答案 3 :(得分:2)
这是一个丑陋的黑客,不推荐。它起作用的原因是and
和or
的短路行为,并且它们返回其参数之一而不是布尔值。使用这种技术会带来引入难以发现的错误的风险,因此不要在新代码中使用它。
以下是and/or
成语如何产生意外结果的示例:
>>> foo = 'foobar'
>>> bar = 'foobar'
>>> x = 0
>>> y = 1
>>> (foo == bar) and x or y # Will this return the value of x if (foo == bar)?
1
请选择较新的表示法:
return "https://" if port == "443" else "http://"
答案 4 :(得分:1)
您可能希望在本文The Peculiar Nature of And and Or in Python中阅读Python的“和/或技巧”。它有点像VBA或VB中的IIF()
,或C风格语言中的?:
。
答案 5 :(得分:0)
这种结构有效,因为它“展开”到以下代码:
a和b - >
if a:
return b
else:
return a
a或b - >
if a:
return a
else:
return b
答案 6 :(得分:0)
有了所有好的答案,我发现这些陈述可以帮助我更好地记住这一点,并使我的大脑工作得很好(并希望在那里有更多的东西):
“和”返回第一个False项(例如,None,“”,[],(),{},0)或最后一项(如果没有)(例如没有找到False)
< / LI>“或”返回第一个True项目或最后一个项目(例如找不到True)**
总结:
请注意,此规则也适用于链接的所有“和”或所有“或”语句