我想要检查一个变量是否存在。现在我正在像这样做:
try:
myVar
except NameError:
# Do something.
除了使用异常之外,还有其他的方法吗?
检查本地变量是否存在:
if 'myVar' in locals():
# myVar exists.
检查全局变量是否存在:
if 'myVar' in globals():
# myVar exists.
检查一个对象是否具有某个属性:
if hasattr(obj, 'attr_name'):
# obj.attr_name exists.
NameError
。 - Petr Viktorinif hasattr(obj, 'attr_name'):
这个方法,它也适用于类:例如 if hasattr(self, 'attr_name'):
。 - Ron Kalian使用尚未定义或设置(隐式或显式)的变量通常是不好的,因为它往往表明程序的逻辑并没有完全经过深思熟虑,并且可能导致不可预测的行为。
如果您确实需要在Python中这样做,以下技巧与您的类似,将确保在使用之前变量具有某些值:
try:
myVar
except NameError:
myVar = None # or some other default value.
# Now you're free to use myVar without Python complaining.
然而(这是我的观点),最好重构您的代码,以避免出现这种情况。
举个例子,以下代码被评论为此答案,以允许从先前点到当前点进行线绘制:
if last:
draw(last, current);
last = current
last
未被绑定到一个值的情况下,在Python中这并没有帮助,因为即使是对last
的检查也会引发异常。更好的想法是确保last
有一个值,可以用来决定它是否有效。那将是类似于以下内容的东西:last = None
# some time passes ...
if last is not None:
draw(last, current);
last = current
这样可以确保变量存在,并且只在需要时使用有效的值。
如果您无法控制变量的初始设置,仍然可以添加代码来强制这样做,方法如上所述:
# Variable 'last' may or may not be bound to a value at this point.
try:
last
except NameError:
last = None
# It will always now be bound to a value at this point.
if last is not None:
draw(last, current);
last = current
一个简单的方法是在一开始初始化它,如下所示:myVar = None
然后稍后:
if myVar is not None:
# Do something
except
语句中,我将事物设置为None。 - Kermitif myVar: # Do something
这样可以避免阅读双重否定。 - jjisnowmyVar
是一个空列表、零、空字符串等,这个条件也应该成立。 - Gabrielif myVar: # Do something
会抛出NameError
异常。请注意保持翻译准确无误,并尽可能使其通俗易懂,但不要改变原意。 - Agile Bean使用try/except是测试变量是否存在的最佳方法。但是,几乎肯定有比设置/测试全局变量更好的方法来完成您要做的任何事情。
例如,如果您想在第一次调用某个函数时初始化模块级变量,则最好使用以下代码:
my_variable = None
def InitMyVariable():
global my_variable
if my_variable is None:
my_variable = ...
对于对象/模块,你也可以
'var' in dir(obj)
例如,
>>> class Something(object):
... pass
...
>>> c = Something()
>>> c.a = 1
>>> 'a' in dir(c)
True
>>> 'b' in dir(c)
False
我假设这个测试将被用在一个函数中,类似于user97370的答案。 我不喜欢那个答案,因为它会污染全局命名空间。 修复的一种方法是改用类:
class InitMyVariable(object):
my_variable = None
def __call__(self):
if self.my_variable is None:
self.my_variable = ...
我不喜欢这个,因为它会使代码变得复杂,并提出类似这样的问题:这应该符合单例编程模式吗?幸运的是,Python允许函数具有属性一段时间了,这给我们带来了这个简单的解决方案:
def InitMyVariable():
if InitMyVariable.my_variable is None:
InitMyVariable.my_variable = ...
InitMyVariable.my_variable = None
# Search for entry.
for x in y:
if x == 3:
found = x
# Work with found entry.
try:
print('Found: {0}'.format(found))
except NameError:
print('Not found')
else:
# Handle rest of Found case here
...
def exists(var):
return var in globals()
然后像下面这样调用函数,将variable_name
替换为您要检查的变量:
exists("variable_name")
将返回True
或False
就像这样:
def no(var):
"give var as a string (quote it like 'var')"
assert(var not in vars())
assert(var not in globals())
assert(var not in vars(__builtins__))
import keyword
assert(var not in keyword.kwlist)
稍后:
no('foo')
foo = ....
foo
不安全使用,你将会得到一个 AssertionError
异常,并指向失败的那一行代码,这时你就会更加了解。以下是一个明显的人为自我引用示例:no('no')
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-88-d14ecc6b025a> in <module>
----> 1 no('no')
<ipython-input-86-888a9df72be0> in no(var)
2 "give var as a string (quote it)"
3 assert( var not in vars())
----> 4 assert( var not in globals())
5 assert( var not in vars(__builtins__))
6 import keyword
AssertionError:
__builtins__
的行应该被替换为:import builtins
assert( var not in vars(builtins))
并且最好在定义后加上return True
行,这样你就可以写出像assert no('foo')
这样更清晰的代码。 - RGD2
myVar
是非常复杂的东西,需要很长时间才能生成/评估,那么try
语句会不会减慢速度? - abcdexec
或元类进行一些疯狂的操作,否则它不会很昂贵。 - user2357112