Is there any expression in python that similar to ruby's ||=
我在Ruby中看到了一个有趣的表达:
1 | a ||="new" |
这意味着,如果未定义a,则"新"值将分配给a;否则,a将与其相同。它在进行数据库查询时很有用。如果设置了该值,我不想触发另一个数据库查询。
所以我在python中尝试了类似的思维方式:
1 | a = a if a is not None else"new" |
它失败了。我认为这是因为如果没有定义a,就不能在python中执行"a=a"。
所以我可以得出的解决方案是检查locals()和globals(),或者使用try…except表达式:
1 | myVar = myVar if 'myVar' in locals() and 'myVar' in globals() else"new" |
或
1 2 3 4 5 6 | try: myVar except NameError: myVar = None myVar = myVar if myVar else"new" |
正如我们所看到的,解决方案并不那么优雅。所以我想问一下,有没有更好的办法?
使用未定义的变量作为"默认值"有点像代码味道。正如您发现的,它失败了,因为如果a不存在,您就不能执行
1 2 | # code with no initialization. . . a ||= blah |
这样做:
1 2 3 4 | a = None # code if a is None: a = blah |
怎么样?
1 2 3 4 | try: a = a except NameError: a ="new" |
它不是很短,但确实清楚地(至少对我来说)解释了代码的意图。
考虑一下使用记忆术,这是一种很好的Python。下面是一些python 2代码:
1 2 3 4 5 6 7 8 9 10 11 12 | # 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的LRU缓存。
在使用之前,尤其是在本地/全局变量中,您应该知道它,而不是猜测它在哪里。你可以写这段代码,但它不是Python。
1 2 3 | a = None # other codes a = a or 'new' |
没事吧
如果您真的想要这种行为,最好在Python中使用
使用globals()和setdefault()的可怕示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | >>> 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' |
下面是一个由这个答案启发而来的变量,关于如何检查是否定义了一个变量:
1 | a = a if"a" in vars() or"a" in globals() else"new" |
它没有那么短,但至少有一条线。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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的观点,您应该避免使用未定义变量的问题,只需在可能不设置该变量的块之前用