在Python中压缩`x if x else y`语句
Posted
技术标签:
【中文标题】在Python中压缩`x if x else y`语句【英文标题】:Compressing `x if x else y` statement in Python 【发布时间】:2012-12-15 20:14:18 【问题描述】:我非常熟悉 Python 的三元运算符方法:
value = foo if something else bar
我的问题很简单:如果没有事先分配,是否可以从返回操作数之一(... if
或 else ...
)引用在 (if ...
) 中评估的术语?
这里的动机是有时我在if ...
中使用表达式,这正是我希望在三元运算中得到的结果;虽然发生这种情况,对于小的表达式,重复它没有问题,但是对于更长的表达式,它会变得有些讨厌。以此为例:
value = info.findNext("b") if info.findNext("b") else "Oompa Loompa"
【问题讨论】:
好吧,Oompa Loompa 很有趣! @AspiringAqib 我们没有任务,但我们仍然可以享受一些oompa loompas (: 嗯,你有解决办法吧? @AspiringAqib 是的,我想这已经足够了,甚至可能是最好的解决方案(:最好继续KISS'in things(: 为什么findNext
不采用可选的默认值,例如get
以及以它为原型的数百种其他方法?那么你根本不需要这个。
【参考方案1】:
没有办法做到这一点,这是故意的。三元 if 只应该用于琐碎的情况。
如果你想使用两次计算的结果,把它放在一个临时变量中:
value = info.findNext("b")
value = value if value else "Oompa Loompa"
一旦你这样做了,很明显你在做一些愚蠢的事情,实际上写这个的pythonic方式是:
value = info.findNext("b")
if not value:
value = "Oompa Loompa"
这实际上比您最初的尝试少了 5 次击键。
如果你真的想要节省击键,你可以这样做:
value = info.findNext("b") or "Oompa Loompa"
但许多风格指南和 BDFL 都不鼓励这样做。
如果您只执行一次,最好更加明确。如果你这样做了六次,那么让findNext
采用可选的默认返回而不是None
,就像所有那些内置函数和stdlib 函数一样简单且更好:
def findNext(self, needle, defvalue=None):
# same code as before, but instead of return None or falling off the end,
# just return defvalue.
那么你可以这样做:
value = info.findNext("b", "Oompa Loompa")
【讨论】:
我实际上对编程有一些奇怪的抽搐:我不喜欢写超过 70 列,我真的很欣赏单行解决方案;这里的问题是关于紧凑性而不是明确的单词数量。不过,我接受您的回答,因为您正在回答我的二进制问题yes/no
。尽管如此,同意使用 or,正如@Ignacio 所指出的那样,毕竟是最好的解决方案。
返回None
与返回null
相同,因此返回just as bad。
@Rubens:编写 1 行解决方案的 Pythonic 方法是将任何复杂的内容封装在显式函数中。如果您可以将defval
添加到findNext
,请执行此操作;如果不能,请编写一个包装器。不同的语言有不同的惯用风格(例如,在 Haskell 中,命名一个你只会调用一次的函数是代码异味),并且不同的语言更强烈地遵循它们的惯用语(例如,在 perl 中,“只有一种方法可以做它”将被视为错误,而不是功能)。但如果你选择了 Python,你应该学习惯用的 Python。
@Tinctorius:None
出现在示例中,因为我认为这是 OP 的原始 findNext
返回的内容,就像 dict.get
和同一模型上的所有其他方法一样。它显然返回 something falsey,并且没有 real 结果可以是falsey
,或者 OP 的代码是错误的,我假设它不是。无论如何,这与OP的问题无关。 (但是,作为旁注:您认为 Haskell 的 Nothing
是否违反了 void 安全性?如果不是,除了静态与动态类型之外,Nothing
和 None
之间有什么区别?)
@abarnert:如果您有动态类型,那么我非常喜欢“默认返回值”方法。抛出KeyError
也很好,但人们可能会发现这会使代码混乱。我认为 Haskell 的 Maybe
根本没有违反 void 安全性。默认情况下,无效的不安全语言使许多类型可以为空。 Maybe
允许您选择可空性。 Haskell 无效不安全的唯一方法是它的底部值(即难以捕捉的终止,如undefined
,或非终止,如fix id
),但要解决这个问题,你的语言会变得更难使用 并且更难实施。【参考方案2】:
根本不要使用if ... else
。相反,请利用 Python 的合并运算符。
value = info.findNext("b") or "Oompa Loompa"
【讨论】:
它是certainly a shortcut,@Rubens。x or y
应该编译成与if bool(x) then x else y
相同的代码。 bool
打电话给.__nonzero__()
。
你可以这样做,但这并不意味着你应该。如果您这样做的次数足够多以至于节省 5 次击键很重要,请修改 findNext
方法以采用默认值。否则,明确写出来。
如果混入了任何falsy的东西,这种事情会烧死你。考虑[] or 'default'
- 这可能是您正在寻找的,也可能不是。以上是关于在Python中压缩`x if x else y`语句的主要内容,如果未能解决你的问题,请参考以下文章
small= x if x<y else y python的这句语法怎么解释?