Python:如果不存在则赋值

Posted

技术标签:

【中文标题】Python:如果不存在则赋值【英文标题】:Python: Assign Value if None Exists 【发布时间】:2011-11-12 09:39:23 【问题描述】:

我是一名刚接触 Python 的 RoR 程序员。我试图找到允许我将变量设置为特定值的语法,前提是它之前没有分配。基本上我想要:

# only if var1 has not been previously assigned

var1 = 4

【问题讨论】:

在什么情况下会引用可能不存在的变量?是否要引用已声明但尚未初始化的变量? 【参考方案1】:

您应该将变量初始化为 None 然后检查它:

var1 = None
if var1 is None:
    var1 = 4

一行可以写成:

var1 = 4 if var1 is None else var1

或使用快捷方式(但建议检查无)

var1 = var1 or 4

或者,如果您没有为变量分配任何内容,则该变量名不存在,因此稍后使用它会引发NameError,您也可以使用该知识来做类似的事情

try:
    var1
except NameError:
    var1 = 4

但我建议不要这样做。

【讨论】:

请注意,如果您想分配一个值,您要么需要 global/nonlocal 声明,要么使用 except UnboundLocalError(并接受该变量将是本地的和全局设置的值将被忽略)。 因为后面的赋值(在except中),var1是一个局部变量,除非sn-p在模块(即全局)级别或者有一行@ 987654332@。访问尚未分配的局部变量会引发 UnboundLocalError 而不是 NameError(为全局名称保留)。 @delnan 我不明白你能举个例子来证明这一点,因为>>> issubclass(UnboundLocalError, NameError) True 哦该死的,我总是忘记那个子类型关系。那么你的代码确实是正确的。很抱歉造成混乱。 如果 var1 是 0var1 = var1 or 4 会伤害你.您可以在 docs.python.org/2/library/stdtypes.html#truth-value-testing 中检查哪些其他内容评估为“假”【参考方案2】:

如果您指的是模块级别的变量,那么您可以使用“globals”:

if "var1" not in globals():
    var1 = 4

但常见的 Python 习惯用法是将其初始化为 None(假设它不是可接受的值),然后使用 if var1 is not None 进行测试。

【讨论】:

这就是疯狂。这会在局部变量上中断,在全局变量上使用 locals() 中断,我认为它们都不适用于非本地变量。要解决这个问题,必须模拟整个范围规则或编写代码假设两者之一。 @delnan:关于本地/非全局,这就是我所说的“如果您指的是模块级别的变量”。关于那个愚蠢的“那是疯狂的”,你应该告诉 OP,而不是我......顺便说一下,答案实际上被告知这不是应该做的事情。【参考方案3】:

这是一种非常不同的编程风格,但我总是尝试重写看起来像的东西

bar = None
if foo():
    bar = "Baz"

if bar is None:
    bar = "Quux"

只是:

if foo():
    bar = "Baz"
else:
    bar = "Quux"

也就是说,我尽量避免出现一些代码路径定义变量而另一些不定义的情况。在我的代码中,从来没有一个路径会导致定义变量集的歧义(事实上,我通常会更进一步,并确保 types 是相同的,无论代码路径如何)。这可能只是个人喜好问题,但我发现这种模式虽然在我编写时不太明显,但在我以后阅读时更容易理解。

【讨论】:

这甚至可以使用bar = "Baz" if foo() else "Quux"在单行中缩短 什么是 foo()?这是如何回答这个问题的?回复不包括根据变量的存在对变量进行条件分配。 小心,如果任何预期值是虚假的(例如,False0''[]),此操作将失败。最好说x = y if x is None else x @mdeous 这是错误的,因为 foo() == False 会使 bar 成为“Quux”。你的 Python 解决方案质量一般。 @HenryHenrinson 与答案中的第二个示例的行为不完全相同吗? (更不用说@Ninjakannon 已经提出了这个问题)【参考方案4】:
var1 = var1 or 4

这可能存在的唯一问题是,如果 var1 是一个错误值,例如 False 或 0 或 [],它将选择 4。这可能是个问题。

【讨论】:

查看 truth value testing 获取评估为 False 的完整列表,其中一些可能会让某些人感到惊讶。【参考方案5】:

IfLoop 的答案(和 MatToufoutu 的评论)非常适合独立变量,但我想为任何尝试对列表、元组或字典中的单个条目执行类似操作的人提供答案。

字典

existing_dict = "spam": 1, "eggs": 2
existing_dict["foo"] = existing_dict["foo"] if "foo" in existing_dict else 3

返回"spam": 1, "eggs": 2, "foo": 3

列表

existing_list = ["spam","eggs"]
existing_list = existing_list if len(existing_list)==3 else 
                existing_list + ["foo"]

返回["spam", "eggs", "foo"]

元组

existing_tuple = ("spam","eggs")
existing_tuple = existing_tuple if len(existing_tuple)==3 else 
                 existing_tuple + ("foo",)

返回("spam", "eggs", "foo")

(不要忘记("foo",) 中的逗号来定义“单个”元组。)

如果您想要做的不仅仅是检查长度并附加到末尾,那么列表和元组解决方案将会更加复杂。尽管如此,这还是说明了您可以做什么。

【讨论】:

你所有的答案都被打破了。 @SébastienDeprez 你确实是对的。感谢您指出。此后我进行了编辑以解决这些问题。【参考方案6】:

我也来自 Ruby,所以我喜欢 foo ||= 7 的语法。

这是我能找到的最接近的东西。

foo = foo if 'foo' in vars() else 7

我见过人们为 dict 这样做:

try:
    foo['bar']
except KeyError:
    foo['bar'] = 7

更新: 但是,我最近发现了这个宝石:

foo['bar'] = foo.get('bar', 7)

如果你喜欢这样,那么对于常规变量,你可以这样做:

vars()['foo'] = vars().get('foo', 7)

【讨论】:

这对于类中的实例变量如何工作? self.foo = ...? @CodeKid self.foo = self.__dict__.get('foo', 7) @CodeKid 或self.foo = getattr(self, 'foo', 7) 这个是唯一能正确处理case var = None的【参考方案7】:

这是我使用的最简单的方法,希望对你有用,

var1 = var1 or 4

仅当 var1NoneFalse0 时,才会将 4 分配给 var1

【讨论】:

它被否决了,但经过一些测试后,我发现它有效。为什么不显示?【参考方案8】:

这里的单线解决方案:

var1 = locals().get("var1", "default value")

如果尚未定义 var1,此解决方案将设置 var1default value,而不是 NameError

这是它在 Python 交互式 shell 中的样子:

>>> var1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'var1' is not defined
>>> var1 = locals().get("var1", "default value 1")
>>> var1
'default value 1'
>>> var1 = locals().get("var1", "default value 2")
>>> var1
'default value 1'
>>>

【讨论】:

以上是关于Python:如果不存在则赋值的主要内容,如果未能解决你的问题,请参考以下文章

python检查目录是否存在,如果不存在则创建

python----------文件操作

python~字典给默认属性赋值使用del关键字,删除赋值,恢复其默认属性

python----------文件操作

Python(day5)文件操作

Python(day5)文件操作