我在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"
正如我们所看到的,解决方案并不那么优雅。所以我想问一下,有没有更好的方法呢?
答案 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
声明它来避免未定义变量的问题。