ChatGPT解决这个技术问题 Extra ChatGPT

确定变量是否在Python中定义[重复]

这个问题在这里已经有了答案:Easy way to check that a variable is defined in python? [重复] (5个回答) 2年前关闭。

您如何知道变量是否已在运行时代码中的特定位置设置?这并不总是很明显,因为(1)可以有条件地设置变量,(2)可以有条件地删除变量。我正在寻找类似 Perl 中的 defined() 或 PHP 中的 isset() 或 Ruby 中的 defined? 之类的东西。

if condition:
    a = 42

# is "a" defined here?

if other_condition:
    del a

# is "a" defined here?
请,请,请不要“有条件地”设置变量。那只是可怕的,可怕的设计。始终、始终、始终提供所有逻辑路径。请不要继续这样做。
+1 给 S.Lott anwser。有办法做到这一点并不意味着您应该在新项目中使用它。
@S.Lott:我不同意。当我使用 import 来“获取”一个“配置文件”(即其中只有分配的文件)时,很可能是那里没有定义一些变量。 import 肯定比 ConfigParser 更便宜/更简单,所以对我来说,实用主义在这里胜过美感。
@STATUS_ACCESS_DENIED:这是合适的默认值。首先设置默认值。然后导入您的配置。现在所有变量都被定义为配置文件中的默认值或覆盖。您可以轻松避免有条件地设置变量。

p
phoenix
try:
    thevariable
except NameError:
    print("well, it WASN'T defined after all!")
else:
    print("sure, it was defined.")

@Aaron:在很多情况下您不知道是否定义了变量。在很多情况下,您可以重构代码以避免这种情况,但不是所有情况。亚历克斯的解决方案是正确的,当由于某些原因无法重构时,它是最好的。问题中的信息不多,所以我相信只有问它的人才能选择处理他的案件的最佳方式。
@Aaron,“应该”是一个 4 个字母的词——例如,没有司机“应该”超过限速,但这并不意味着你不会对那些仍然这样做的人采取所有适当和必要的预防措施。维护脆弱的、测试不足的遗留代码以及从其他人那里继承的有些破损的设计是生活中的一个事实,那些只能从头开始考虑大爆炸重写而不是谨慎和渐进式的人需要重新阅读 Joel 的 9 年-旧论文joelonsoftware.com/articles/fog0000000069.html
这场辩论比答案本身更有趣,顺便说一句,答案是 100% 正确的,并且可以让你优雅地处理糟糕的遗留代码。
应为例外情况保留例外,而不是用作'if'的混蛋 :-(
@einpoklum,Python 在几乎 every for 语句中使用异常 StopIteration - 这就是迭代器如何让它知道它已经完成了。当然,要完成迭代与“例外情况”相去甚远——事实上,人们期望大多数 迭代终止。因此,很明显,您对“应该”如何使用异常的观点正确地适用于 Python(其他语言有不同的语用学和问题 cannot 被正确地视为“语言不可知论”,如您所指的 Q)。
J
John La Rooy

'a' in vars() or 'a' in globals()

如果您想学究气,也可以检查内置函数
'a' in vars(__builtins__)


这应该是我相信的答案。见stackoverflow.com/questions/843277/…
这是一个非常地道的答案。这里有一个强大的地图用例;例如,if "prop2" in {"prop0": None, "prop1": None}:
截至今天 - 2018 年 6 月:我不认为 vars(__builtin__) 仍然有效(对于 Python 2 或 3)。我相信 vars(__builtins__) (注意复数 ;-)) 现在应该用于两个版本(测试:Python 2.7.10 和 Python 3.6.1)。
为什么不是 locals(),为什么不是 dir()?
@AndresVia globals()locals() 的超集。
d
divegeek

我认为最好避免这种情况。写得更干净更清晰:

a = None
if condition:
    a = 42

如果您喜欢这样做,您应该使初始值唯一,以便您可以区分设置 aNone 即。 UNDEFINED=object();a=UNDEFINED 然后您可以使用 a is not UNDEFINED 进行测试
这是 None 的常见用法。从字面上看,这就是 None 的语义——什么都不是,nada,zip。它存在,但“没有价值”。如果 None 可以出现在作业等中,则使用非 None 值很有用,但这并不常见,因此避免 None 应该是标准做法。例如,在问题中,a 永远只能是 42 或未定义。将 undefined 更改为 None 不会导致信息丢失。
这是方式,不知道为什么人们认为使用 LONG 和 DIRTY try/except 构造来完成这项工作。在您不想将默认值硬编码到参数列表中(您只需将默认值定义为类成员)的类成员函数中使用关键字 args 时,这也非常有用。
@DevinJeanpierre 这不一定是真的。如果您想为 JSON API 创建一些客户端库,将 null 值视为与未指定值不同(例如,None 将实际 JSON 值设置为 null,而未指定将其排除在 JSON 之外消息,这使得 API 使用默认值或从其他属性计算),您需要区分 NoneUndefined,或 None 和 JSON null。认为 None 不能或不应该被用作与明确未指定或未定义的值不同的想法是非常短视的。
提供默认值(这就是这个答案所做的)与测试变量的存在有很大不同。用例中可能有很多重叠,但是如果您想查看是否已定义某些内容,您将永远不会知道使用此方法。
J
Jerub
try:
    a # does a exist in the current namespace
except NameError:
    a = 10 # nope

例外只应在例外情况下使用。请参阅this discussion
@einpoklum 对于大多数语言都是如此,但在 Python 中更经常使用异常,请参见例如 stackoverflow.com/questions/3086806
嗯,很奇怪,但很明显。我仍然认为这不是一个好主意(TM),但是,不能与社区习俗争论。
最好使用上面提到的if 'a' in vars() or 'a' in globals()解决方案,它不需要异常
try/except 是你在 python 中所做的。一种语言中的代码异味是另一种语言中的特征。
D
Denis Otkidach

对于这种特殊情况,最好使用 a = None 而不是 del a。这将减少分配给对象 a 的引用计数(如果有),并且在未定义 a 时不会失败。请注意,del 语句不直接调用对象的析构函数,而是将其与变量解除绑定。当引用计数为零时调用对象的析构函数。


x
xsreality

可能需要这样做的一种可能情况:

如果您使用 finally 块关闭连接但在 try 块中,则程序在定义连接之前以 sys.exit() 退出。在这种情况下,将调用 finally 块并且连接关闭语句将失败,因为没有创建连接。


那么也许连接关闭不应该在finally中完成?