Python 将多个变量初始化为相同的初始值

Python initialize multiple variables to the same initial value

我已经解决了这些问题,

  1. Python assigning multiple variables to same value? list behavior
    concerned with tuples, I want just variables may be a string, integer or dictionary
  2. More elegant way of declaring multiple variables at the same time
    The question has something I want to ask, but the accepted answer is much complex

所以我要实现的目标是,

我如下声明变量,我想将这些声明减少到尽可能少的代码行。

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 = {}

什么是最简单、易于维护的?

(
    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 = {}

我就是这样。

首先我建议你不要这样做。它不可读且非 Pythonic。但是,您可以使用以下内容减少行数:

details, product_base, product_identity, category_string, store_id, image_hash, image_link_mask, results = [None] * 8
abort = False
data = {}

我同意其他答案,但想在这里解释一下重点。

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.

我使用了一个单行 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)]

这并没有直接回答问题,但它是相关的——我使用一个空 class 的实例来对相似的属性进行分组,所以我不必弄乱我的 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)

以前答案的混合:

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 类型的可变变量来优化深度复制调用。可能错过了其他一些。如果有人找到更好的方法来检查可变性,请随时分享。尽管如此,无论您的用例是什么,这都可能过度设计...

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)

在参与@belgacea 的回答下的讨论后,我想post我认为最好的那个答案的变体:

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) returns 为真,因此尝试避免没有任何好处对不需要深度复制的值调用 deepcopy

我还将函数的签名和名称更改为我认为可以在使用它的地方生成更好的自文档化代码的内容。