Python中与Perl/Ruby ||= 相等的语法

9

可能重复:
Python条件赋值运算符

非常抱歉问这么简单的问题,但是谷歌搜索 ||= 并没有什么帮助 ;)

在Python中是否有等价于Ruby和Perl中的 ||= 语句的东西?

例如:

foo = "hey"
foo ||= "what"    # assign foo if it's undefined
# foo is still "hey"

bar ||= "yeah"
# bar is "yeah"

此外,这类东西的通用术语是什么?条件赋值是我最初的猜测,但维基百科页面并不完全符合我的想法。

是的,看起来是重复的。谢谢Adam! - benui
3
如果$foo已经为假,那么$foo ||= "what"将重新赋值$foo。当然,undef是假的,但是零和空字符串也是。要只重新赋值未定义的值,请改用斜杠,例如$foo //= "what" - Borodin
请注意,//(以及它的扩展形式,//=)是在 Perl 5.10 中添加的。如果您仍然停留在 5.8.x 版本上,则无法使用 //=(如果可能的话,强烈建议升级版本)。 - Dave Sherohman
3个回答

11

稍微详细一点,但最简单的方法是

foo = "hey"
foo = foo or "what"
#foo is still "hey"

bar = None
bar = bar or "yeah"
#bar is "yeah"

你也可以使用三元运算符。

bar = None
bar = bar if bar else "yeah"

不过,如果我理解正确的话,||=会在没有定义变量的情况下赋值,而不会报错?我以前不知道。

要在局部作用域中实现这个功能,可以使用这个“丑陋”的方法:

bar = locals()['bar'] if 'bar' in locals() else 'yeah'

编辑:

刚刚看到重复问题,它也有很多解决方案 :) 对于那些懒得查找的人,它们还包括一个比我上一个更好的变体

foo = foo if 'foo' in locals() else 'hey'

但是这种方式不适用于未定义的变量,只有假值才会被替换,而未定义的变量会引发NameError异常。然而下面这个方法仅适用于未定义的变量,并始终保留相同的现有假值,就像Perl中的//=操作符所做的一样。

foo = locals().get('foo','hey')

当然,还有人使用了异常 :(

try:
   v
except NameError:
   v = 'bla bla'

不,||= 只有在变量为 false 时才会重新赋值。请看我在问题中的评论。你为什么会期望出现投诉呢? - Borodin
谢谢回复,一开始我没有注意到微妙的差别。bar = None 是必需的,否则会抛出 NameError。要实现相同的行为,您需要使用 locals()['bar'] 代码片段。再次感谢 :) - benui
@borodin 我不是 Ruby 程序员,我只用它来做一些像 Chef 这样的傻瓜式东西。我只是想说我不知道在 Ruby 中 undef 是 falsey 的,因为在 Python 中并非如此(未定义的引用会抛出异常)。无论如何,感谢您的评论,我学到了东西 :) - Matt Luongo

3

在Python中,你很少会遇到未定义的变量,如果确实出现了这种情况,通常意味着你犯了错误。然而,方便地是,通常用作默认值的值类型(空容器、零长度字符串、零和None)在Python中都是“假”的,因此你有时会看到像这样的代码,利用了Python中布尔运算符的工作方式:

name = name or "Guido"   # if name is empty, set it to "Guido"
numb = numb or 42        # if numb is zero, set it to 42

这种方法有效的原因是,如果第一个参数是“真值”(即非零、非空或True),Python就会停止评估或运算,这被称为短路,无论哪种情况,它都返回实际参数,而不仅仅是True或False。所以,如果name是"Jim",那么"Jim" or "Guido"的结果将是"Jim",因为"Jim"是一个非零长度的字符串,因此为“真值”。
当你不知道正在处理的值的类型和/或“假值”是一个有效值时,当然,这种方法不能很好地工作。但是,在处理配置文件和raw_input()等内容时,它会相当有效,因为缺少值会返回一个空字符串:
name = raw_input("What is your name? ") or "Guido"

另一个常见的习语用于处理字典中的项。 字典类的get()方法允许您指定默认值,以用于字典中不存在该变量的情况。

name = values.get("name", "Guido")

当您的函数使用**kwargs约定传递关键字参数时,可以使用此功能。您也可以将其与变量一起使用,因为globals()locals()函数分别返回当前作用域中所有全局或本地变量的字典:

name = locals().get("name", "Guido")

然而,正如我所说,你在Python中很少会遇到实际未定义的变量。例如,在Web框架等情况下,你将作为字典传递查询字符串参数,并且可以使用该字典的.get() 方法。
在极少数情况下,如果名称实际上不存在(例如,您的配置文件是以Python语法写成的,并且您将其作为Python模块导入而不是解析它,并且您希望用户能够省略某些值......或者其他同样疯狂的情况),那么你可以使用getattr(),它(就像字典的.get())接受一个默认值:
import config
name = getattr(config, "name", "Guido")    # rather than just name.config

或者让它抛出一个NameError并捕获它。


1

不确定名字。我能想到的最好的是:

>>> a = 'foo'
>>> a = 'a' in locals() and a or 'what'
>>> a
'foo'
>>> b = 'b' in locals() and b or 'yeah'
>>> b
'yeah'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接