Python将多个变量初始化为相同的初始值
Posted
技术标签:
【中文标题】Python将多个变量初始化为相同的初始值【英文标题】:Python initialize multiple variables to the same initial value 【发布时间】:2016-01-24 17:24:01 【问题描述】:我已经解决了这些问题,
Python assigning multiple variables to same value? list behavior 关于元组,我只希望变量可以是字符串、整数或字典 More elegant way of declaring multiple variables at the same time 这个问题有一些我想问的问题,但接受的答案非常复杂
所以我想要达到的目标,
我声明变量如下,我想将这些声明减少到尽可能少的代码行。
details = None
product_base = None
product_identity = None
category_string = None
store_id = None
image_hash = None
image_link_mask = None
results = None
abort = False
data =
什么是最简单、易于维护的?
【问题讨论】:
你会使用字典。 这很复杂,我得打电话给dicitonary['details']
和KeyErrors
很烂,而且IDE 不会突出显示无效键而是变量。如果我必须使用details = dicitonary['details']
,我最好使用details = None
,而不是这一轮的dict创建、查找和KeyErrors。
如何定义复杂?
@CrakC 见上面的评论。
a,b=(True,)*2
或a=b=True
【参考方案1】:
我同意其他答案,但想在这里解释重点。
None 对象是单例对象。将 None 对象分配给变量的次数,使用相同的对象。所以
x = None
y = None
等于
x = y = None
但是你不应该对 python 中的任何其他对象做同样的事情。例如,
x = # each time a dict object is created
y =
不等于
x = y = # same dict object assigned to x ,y. We should not do this.
【讨论】:
不回答问题【参考方案2】:首先我建议你不要这样做。它不可读且非 Pythonic。但是,您可以通过以下方式减少行数:
details, product_base, product_identity, category_string, store_id, image_hash, image_link_mask, results = [None] * 8
abort = False
data =
【讨论】:
哇,这个 [None]*8 看不懂,但是读起来很容易【参考方案3】:(
details,
producy_base,
product_identity,
category_string,
store_id,
image_hash,
image_link_mask,
results,
) = (None, None, None, None, None, None, None, None)
abort = False
data =
我就是这样做的。
【讨论】:
【参考方案4】:我使用了一个单行 lambda 函数来帮助我解决这个问题。
nones = lambda n: [None for _ in range(n)]
v, w, x, y, z = nones(5)
lambda 和这个是一样的。
def nones(n):
return [None for _ in range(n)]
【讨论】:
对不起,我是个菜鸟,使用 lambda 而不是直接使用它有什么好处吗? a, b, c = (None for _ in range(3))【参考方案5】:以前的答案的混合:
from copy import deepcopy
def default(number, value = None):
if type(value) is dict or object:
return [deepcopy(value) for _ in range(number)]
else:
return [value] * number
o, p, q, r, s = default(5)
t, u = default(2, false)
v, w, x = default(3, )
class GPU:
def __init__(self, m, p):
self.model = m
self.price = p
rtx_3080 = GPU("RTX 3080", 99999)
y, z = default(2, rtx_3080)
编辑:
尝试通过更好地处理 pandas/numpy 类型的可变变量来优化 deepcopy 调用。可能漏掉了一些其他的。如果有人找到更好的方法来检查可变性,请随时分享。尽管如此,无论您的用例是什么,这都可能过度设计......
import builtins
from copy import deepcopy
from numbers import Number
from pandas import api, DataFrame
mutables = (dict, list, set, DataFrame)
immutables = (str, tuple, frozenset, Number)
def is_built_in_type(var):
return type(var).__name__ in dir(builtins)
def is_mutable(var):
return var is not None and (api.types.is_list_like(var) or isinstance(var, mutables) or not is_built_in_type(var))
def is_immutable(var):
return var is None or isinstance(var, immutables)
def default(number, value=None):
if is_mutable(value):
return [deepcopy(value) for _ in range(number)]
elif is_immutable(value):
return [value] * number
else:
raise ValueError("Unexpected value type")
a, b, c, d, e = default(5)
f, g, h = default(3, False)
i, j = default(2, "False")
k, l, m, n = default(4, (3, 2, 1))
o, p = default(2, 3.14159265358979)
q, r, s = default(3, [1, 2, 3])
t, u = default(2, )
v, w, x = default(3, DataFrame('col1': [7, 13, 42, 73, 666], 'col2': [1, 0.6, 2, 1.4, 0.3]))
class GPU:
def __init__(self, m, p):
self.model = m
self.price = p
rtx_3080 = GPU("RTX 3080", 99999)
y, z = default(2, rtx_3080)
【讨论】:
v, w, x = default(3, )
将无法按预期工作:因为您在对 default()
的调用中实例化了
,实际上您将 same 字典分配给每个变量:运行 @ 987654326@,然后打印w
,你会看到w=='a': 'b'
。
如果你真的想保留这种方法,你可以通过返回一个值的深拷贝数组来修补这个代码。这将工作return [copy.deepcopy(value) for _ in range(number)]
。
@joanis 感谢您的关注。我编辑了我的答案。
好多了,它通常可以工作,尽管我怀疑 deepcopy 行被系统调用,因为 type(value) is dict or object
与 (type(value) is dict) or object
相同,并且在布尔上下文中评估的 object
是总是正确的。虽然我认为无论如何优化都是多余的,但您真正想要测试的是value
是否可变。在 Python 中,一切都是一个对象,所以像 if isinstance(value, dict) or isinstance(value, object):
这样的东西,我认为它更接近你想要做的,在系统上也是正确的。
这让代码变得复杂了很多。实际上,我会坚持使用一条无条件的 deepcopy 行,前提是 None
、False
、True
、()
的 deepcopy 都非常便宜,因此不值得尝试优化该调用。此外,我刚刚测试过,字符串或仅包含不可变的元组的深拷贝结果证明是由copy.deepcopy
本身优化回引用副本,所以看起来我们试图添加的所有魔法都已经存在.因此,为了代码的简单性,并且不影响性能,我将 default()
设为单行函数。【参考方案6】:
在参与了@belgacea 答案下的讨论后,我想发布我认为最好的答案的变体:
import copy
def duplicate(value, n):
return [copy.deepcopy(value) for _ in range(n)]
a, b, c = duplicate([0], 3)
o, p, q, r, s = duplicate(None, 5)
t, u = duplicate(False, 2)
v, w, x = duplicate(, 3)
y, z = duplicate(MyClass(), 2)
在所有情况下,deepcopy()
向我们保证,可变对象不会在一起初始化的不同变量之间共享,这是要避免的重要问题。
但是我已经将代码简化为最简单的表达式,利用deepcopy
已经很好地优化以在其输入不可变时执行浅拷贝这一事实。我已经用字符串和元组对此进行了测试,如果x
是递归不可变的,例如x = ((1,2),"foo")
,那么x is copy.deepcopy(x)
返回True,因此尝试避免对不可变的值调用deepcopy
没有任何好处需要深拷贝。
我还将函数的签名和名称更改为我认为可以在使用它的地方生成更好的自记录代码的东西。
【讨论】:
【参考方案7】:这并没有直接回答问题,但它是相关的——我使用一个空类的实例来对相似的属性进行分组,所以我不必通过列出来弄乱我的 init 方法他们都。
class Empty:
pass
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.w = Empty() # widgets
self.master = master
self.pack()
self.create_widgets()
def create_widgets(self):
self.w.entry = tk.Entry(self, bg="orange", fg="black", font=FONT)
What is the difference between SimpleNamespace and empty class definition?
【讨论】:
以上是关于Python将多个变量初始化为相同的初始值的主要内容,如果未能解决你的问题,请参考以下文章
如何将@NSManaged 对象类中的变量初始化为 JSON 值?