在python中是否有类似于ruby的|| =的表达式

时间:2012-07-20 07:09:29

标签: python ruby expression

我在Ruby中遇到了一个有趣的表达式:

a ||= "new"

这意味着如果未定义a,则将“new”值分配给a;否则,a将与它相同。在进行一些数据库查询时很有用。如果设置了该值,我不想触发另一个数据库查询。

所以我在Python中尝试了类似的心态:

a = a if a is not None else "new"

失败了。我认为这是因为你不能在Python中做“a = a”,如果没有定义。

所以我可以出来的解决方案是检查locals()和globals(),或者使用try ... except expression:

myVar = myVar if 'myVar' in locals() and 'myVar' in globals() else "new"

try:
    myVar
except NameError:
    myVar = None

myVar = myVar if myVar else "new"

正如我们所看到的,解决方案并不那么优雅。所以我想问一下,有没有更好的方法呢?

6 个答案:

答案 0 :(得分:5)

使用未定义的变量作为"默认"有点代码味道。正如您所发现的那样,它失败了,因为如果已经存在,则无法a = a # code with no initialization. . . a ||= blah 最好使用某个默认值(如None)初始化变量,然后检查它。所以你几乎找到了解决方案。唯一的事情是,不要让你的变量未经注册而试图使用"不存在"作为"失踪"值,您应该显式初始化它。所以,而不是这样做:

a = None
# code
if a is None:
    a = blah

这样做:

{{1}}

答案 1 :(得分:3)

怎么样?

try:
    a = a
except NameError:
    a = "new"

这不是很短,但很清楚(至少对我来说)解释代码的意图。

答案 2 :(得分:1)

如果你真的想要这种行为,你最好使用dict在Python中,例如:d.get('a', 'new')。这意味着您可以使用globals() / locals()get('a', 'new')来解决问题,但这通常不是在Python中执行操作的方法 - 每个名称绑定都应该具有初始值,即使它是某种类型of sentinel值(例如None)。

使用globals()并使用setdefault()的可怕示例

>>> a
Traceback (most recent call last):
  File "<pyshell#66>", line 1, in <module>
    a
NameError: name 'a' is not defined
>>> globals().setdefault('a', 'new')
'new'
>>> a
'new'
>>> a = 'old'
>>> globals().setdefault('a', 'new')
'old'
>>> a
'old'

答案 3 :(得分:1)

Pythonic是你应该在使用之前知道它,特别是在本地/全球变量中,而不是猜测它在哪里。您可以编写此代码,但它不是pythonic

a = None
# other codes
a = a or 'new'

没事。

答案 4 :(得分:1)

考虑使用memoization,这是非常Pythonic。这是一些Python 2代码:

# Backport of Python 3's lru_cache
# pip install functools32
from functools32 import lru_cache

@lru_cache()
def expensive_db_query(arg):
    print "Running expensive db query for", arg
    return arg[::-1]

expensive_db_query("spam") # prints "Running expensive db query for spam"
expensive_db_query("spam") # No output
expensive_db_query("eggs") # prints "Running expensive db query for eggs"

如果您希望在经过足够的时间后让缓存忘记值并再次查询数据库,请查看Ilialuk's lru cache

答案 5 :(得分:0)

这是一个受this answer启发的关于如何检查变量是否已定义的变体:

a = a if "a" in vars() or "a" in globals() else "new"

它并不短,但它至少有一条线。

In [1]: a
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-1-60b725f10c9c> in <module>()
----> 1 a

NameError: name 'a' is not defined

In [2]: a = a if "a" in vars() or "a" in globals() else "new"

In [3]: a
Out[3]: 'new'

In [4]: a = "A exists!"

In [5]: a = a if "a" in vars() or "a" in globals() else "new"

In [6]: a
Out[6]: 'A exists!'

那就是说,我同意BrenBarn你应该通过在你可能没有设置它的块之前用a=None声明它来避免未定义变量的问题。