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 是 0
,var1 = 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()?这是如何回答这个问题的?回复不包括根据变量的存在对变量进行条件分配。
小心,如果任何预期值是虚假的(例如,False
、0
、''
、[]
、
),此操作将失败。最好说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 = ...? @CodeKidself.foo = self.__dict__.get('foo', 7)
@CodeKid 或self.foo = getattr(self, 'foo', 7)
这个是唯一能正确处理case var = None的【参考方案7】:
这是我使用的最简单的方法,希望对你有用,
var1 = var1 or 4
仅当 var1
是 None
、 False
或 0
时,才会将 4
分配给 var1
【讨论】:
它被否决了,但经过一些测试后,我发现它有效。为什么不显示?【参考方案8】:这里的单线解决方案:
var1 = locals().get("var1", "default value")
如果尚未定义 var1
,此解决方案将设置 var1
为 default 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:如果不存在则赋值的主要内容,如果未能解决你的问题,请参考以下文章