提问人:Max Frai 提问时间:5/9/2009 最后编辑:Mateen UlhaqMax Frai 更新时间:5/22/2023 访问量:1702096
如何检查变量是否存在?
How do I check if a variable exists?
答:
catch
在 Python 中被调用,但 except
在 Python 中。除此之外,对于这种简单的情况也没关系。AttributeError
可用于检查对象是否具有属性。
要检查局部变量是否存在:
if 'myVar' in locals():
# myVar exists.
要检查全局变量是否存在:
if 'myVar' in globals():
# myVar exists.
要检查对象是否具有属性,请执行以下操作:
if hasattr(obj, 'attr_name'):
# obj.attr_name exists.
评论
NameError
if hasattr(obj, 'attr_name'):
if hasattr(self, 'attr_name'):
使用尚未定义或设置(隐式或显式)的变量通常是一件坏事,因为它往往表明程序的逻辑不一定经过完全考虑,并且可能导致不可预测的行为。
如果你确实需要在 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
在未绑定到值的情况下,这在 Python 中根本无济于事,因为即使检查也会引发异常。一个更好的主意是确保确实有一个值,一个可以用来决定它是否有效的值。这将是这样的:last
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
评论
使用 try/except 是测试变量是否存在的最佳方法。但几乎可以肯定的是,有一种比设置/测试全局变量更好的方法来做你正在做的事情。
例如,如果你想在第一次调用某个函数时初始化一个模块级变量,你最好使用这样的代码:
my_variable = None
def InitMyVariable():
global my_variable
if my_variable is None:
my_variable = ...
评论
处理这种情况的一种方法通常是不显式检查变量是否存在,而是继续将可能不存在的变量的第一次用法包装在 try/except NameError 中:
# 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
...
我将假设该测试将用于一个函数中,类似于 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
对于对象/模块,您还可以
'var' in dir(obj)
例如
>>> class Something(object):
... pass
...
>>> c = Something()
>>> c.a = 1
>>> 'a' in dir(c)
True
>>> 'b' in dir(c)
False
一个简单的方法是在第一次说的时候初始化它myVar = None
然后稍后:
if myVar is not None:
# Do something
评论
myVar = none # do stuff... if not myVar: # give myVar a value myVar = 'something'
except
if myVar: # Do something
myVar
if myVar: # Do something
NameError
我创建了一个自定义函数。
def exists(var):
return var in globals()
然后调用函数,如下所示,替换为要检查的变量:variable_name
exists("variable_name")
将返回或True
False
评论
短款:
my_var = some_value if 'my_var' not in globals() else my_var:
评论
这是我的场景:
for i in generate_numbers():
do_something(i)
# Use the last i.
我无法轻易确定可迭代对象的长度,这意味着它可能存在,也可能不存在,这取决于可迭代对象是否产生空序列。i
如果我想使用最后一个可迭代对象(空序列不存在),我可以做以下两件事之一:i
i
i = None # Declare the variable.
for i in generate_numbers():
do_something(i)
use_last(i)
或
for i in generate_numbers():
do_something(i)
try:
use_last(i)
except UnboundLocalError:
pass # i didn’t exist because sequence was empty.
第一种解决方案可能有问题,因为我无法判断(取决于序列值)是否是最后一个元素。第二种解决方案在这方面更为准确。i
评论
use_last(i)
UnboundLocalError
hasattr
这样:
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__
return True
assert no('foo')
对于对象,也是一种可能性,使用.__dict__
class A(object):
def __init__(self):
self.m = 1
a = A()
assert "m" in a.__dict__
assert "k" not in a.__dict__
它可能不具有性能,但您可以将解决方案推广为同时检查局部变量和全局变量的函数。
import inspect
def exists_var(var_name):
frame = inspect.currentframe()
try:
return var_name in frame.f_back.f_locals or var_name in globals()
finally:
del frame
然后你可以像这样使用它:
exists_var('myVar')
简单的一行:
a=1
exec("try: a \nexcept NameError: print('Does not exist.')\nelse:print(a)")
并做一些事情:
exec("def my_try(): \n\ttry: a \n\texcept NameError: print('Does not exist.Creating a=');a=1;print(a);\n\telse:print(a)\n\n\nmy_try()")
评论
myVar
try
exec