Python相当于Perl / Ruby || =

时间:2012-01-30 05:16:31

标签: python ruby perl

  

可能重复:
  Python conditional assignment operator

为这么简单的问题道歉,但谷歌搜索||=并不是很有帮助;)

Python中是否存在与Ruby和Perl中存在的||=语句相同的内容?

例如:

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

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

这样的一般术语是什么?条件分配是我的第一次猜测,但Wikipedia page并不是我想到的。

3 个答案:

答案 0 :(得分:6)

稍微冗长一点,但最简单的是

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。下一个,OTOH,只适用于未定义的,并始终保持相同的预先存在的假值,正如@Borodin所说的那样在Perl中是//=

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

当然,有人使用了例外:(

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

答案 1 :(得分:2)

你几乎没有在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

这样做的原因是如果第一个参数是“truthy”,Python停止评估or,这称为短路,并且在任何一种情况下返回实际参数,而不仅仅是TrueFalse,作为结果。因此,如果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并抓住它。

答案 2 :(得分:1)

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

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