如何检查变量是否存在?
- 2024-12-06 08:39:00
- admin 原创
- 83
问题描述:
我想检查一个变量是否存在。现在我正在做这样的事情:
try:
myVar
except NameError:
# Do something.
还有其他没有例外的方法吗?
解决方案 1:
检查局部变量是否存在:
if 'myVar' in locals():
# myVar exists.
检查全局变量是否存在:
if 'myVar' in globals():
# myVar exists.
检查对象是否具有属性:
if hasattr(obj, 'attr_name'):
# obj.attr_name exists.
解决方案 2:
使用尚未定义或设置(隐式或显式)的变量通常是一件坏事,因为它往往表明程序的逻辑不一定经过完全考虑,并且可能会导致不可预测的行为。
如果您确实需要在 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
如果 wherelast
尚未绑定到值,那么在 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
解决方案 3:
一个简单的方法是首先初始化它myVar = None
然后后来:
if myVar is not None:
# Do something
解决方案 4:
对于对象/模块,您还可以
'var' in dir(obj)
例如,
>>> class Something(object):
... pass
...
>>> c = Something()
>>> c.a = 1
>>> 'a' in dir(c)
True
>>> 'b' in dir(c)
False
解决方案 5:
使用 try/except 是测试变量是否存在的最佳方法。但几乎可以肯定,无论你做什么,都有比设置/测试全局变量更好的方法。
例如,如果您想在第一次调用某个函数时初始化模块级变量,那么最好使用如下代码:
my_variable = None
def InitMyVariable():
global my_variable
if my_variable is None:
my_variable = ...
解决方案 6:
我将假设测试将在函数中使用,类似于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
解决方案 7:
catch
在 Python 中调用except
。除此之外,对于这种简单的情况来说,它就足够了。有一个AttributeError
可以用来检查对象是否具有属性的。
解决方案 8:
我创建了一个自定义函数。
def exists(var):
return var in globals()
然后调用如下函数,替换variable_name
您想要检查的变量:
exists("variable_name")
将返回True
或False
要检查 Python 中局部范围内是否存在变量,可以使用该locals()
函数,该函数返回包含所有局部变量的字典。您可以修改exists
函数以检查全局和局部范围,如下所示:
def exists(var):
return var in globals() or var in locals()
你可以通过以下方法检查局部范围内的变量是否存在:
def my_function():
local_var = 42
print(exists('local_var'))
my_function() # Output: True
print(exists('local_var')) # Output: False
在上面的例子中,because中的exists('local_var')
returns是在函数内部本地定义的。但是,它在函数外部返回,因为在全局范围内不可访问。True
`my_functionlocal_var
False`local_var
解决方案 9:
处理这种情况的一种常用方法是不明确检查变量是否存在,而是直接将可能不存在的变量的第一次使用包装在 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
...
解决方案 10:
就像这样:
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:
解决方案 11:
它可能性能不佳,但您可以将解决方案推广到检查局部变量和全局变量的函数。
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')
解决方案 12:
简短版本:
my_var = some_value if 'my_var' not in globals() else my_var:
解决方案 13:
这是我的情况:
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
是最后一个元素。 在这方面,第二个解决方案更准确。
解决方案 14:
对于对象来说也是一种可能性,使用__dict__
。
class A(object):
def __init__(self):
self.m = 1
a = A()
assert "m" in a.__dict__
assert "k" not in a.__dict__
解决方案 15:
简单一行:
a=1
exec("try: a
except NameError: print('Does not exist.')
else:print(a)")
并做一些事情:
exec("def my_try():
try: a
except NameError: print('Does not exist.Creating a=');a=1;print(a);
else:print(a)
my_try()")
解决方案 16:
嗯。我只是像这样简单地包装变量:
globals().get('myVar', <non-existant-value>)
或者 ...
locals().get('myVar', <non-existant-value>)
根据范围,<non-existant-value>
您知道会超出范围的东西在哪里,例如None
或False
。这适用于我遇到的 99% 的情况。始终避免过度设计的诱惑。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理必备:盘点2024年13款好用的项目管理软件