繁体   English   中英

如何检查变量是否存在?

[英]How do I check if a variable exists?

我想检查变量是否存在。 现在我正在做这样的事情:

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.

使用尚未定义或设置(隐式或显式)的变量在任何语言中通常都是一件坏事,因为它往往表明程序的逻辑没有被正确考虑,并且很可能导致在不可预测的行为中。

如果您需要在 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

这确保了变量存在,并且只有在它对你需要的东西有效时才使用它。 这就是我假设if last本来是在注释代码做(但没有),你仍然可以添加代码,迫使这个,如果你有超过变量的初始设置无法控制,用异常的方法以上:

# 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

使用 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's answer 我不喜欢那个答案,因为它会污染全局命名空间。 修复它的一种方法是改用类:

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

except在 Python 中调用catch except 除此之外,对于这种简单的情况,这很好。 AttributeError可用于检查对象是否具有属性。

处理这种情况通常很有效的一种方法是不显式检查变量是否存在,而是继续将可能不存在的变量的第一次使用包装在 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
  ...

我创建了一个自定义函数。

def exists(var):
     return var in globals()

然后调用函数,如下所示将variable_name替换为您要检查的变量:

exists("variable_name")

将返回TrueFalse

短变体:

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.

我无法轻易确定iterable长度,这意味着i可能存在也可能不存在,这取决于 iterable 是否产生空序列。

如果我想使用可迭代对象的最后一个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是否是最后一个元素。 在这方面,第二种解决方案更准确。

像这样:

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: 

对象也有可能,使用__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')

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM