【问题标题】:Python class variable is shared with all instances [duplicate]Python类变量与所有实例共享[重复]
【发布时间】:2021-07-04 23:07:36
【问题描述】:
class list_class:
        def __init__(self, list_=[]):
                self.list_ = list_

        def add_item(self, item):
                self.list_ += [item]
>>> x = list_class()
>>> y = list_class()
>>> x.list_
[]
>>> y.list_
[]
>>> x.add_item(1)
>>> x.list_
[1]
>>> y.list_
[1]

为什么在 x 上调用 add_item() 会改变两个实例上的 list_ 变量?

【问题讨论】:

    标签: python python-3.x python-class


    【解决方案1】:

    在方法参数中使用list_=[] 是一个糟糕的 Python 习惯用法,原因您已经发现。请改用以下内容:

    class ListClass:
        def __init__(self, list_=None):
            if list_ is None:
                list_ = []
            self.list_ = list_
    
        def add_item(self, item):
            self.list_.append(item)
    

    list_ 在最初解析 __init__ 时设置为 []。然而,列表是可变的,并且不会在分配时复制。因此,当__init__ 方法运行时,每次都使用相同的初始列表。通过上述替换,每次运行__init__ 时都会将list_ 分配给一个new 列表,从而避免了问题。 dict 作为函数参数值的默认值也是如此。 list 或 dict 是否为空或包含值都没有关系(__init__(self, list_=[5]) 会遇到同样的问题:不要在函数参数中使用可变变量作为默认值。

    the warning in the tutorial section of default function arguments

    其他更多的 Pythonic 习语使用 CamelCase 作为类名,并使用 somelist.append(item) 而不是 somelist += [item]

    【讨论】:

      【解决方案2】:

      我见过几次,但不记得最终原因。解决方案是不要(或永远)在你的函数/类中声明空的迭代。

      class List_Class:
          def __init__(self, list_):
              self.list_ = list_
      
          def add_item(self, item):
              self.list_ += [item]
      
      
      x = List_Class(list())
      y = List_Class(list())
      print(x.list_)
      print(y.list_)
      x.add_item(1)
      print(x.list_)
      print(y.list_)
      

      【讨论】:

      • “解决方案是不要(或永远)在你的函数/类中声明空的可迭代对象”:你可以将函数参数设置为默认值 '' 就好了,并且字符串是可迭代的.而使用list_=[5](非空可迭代)会出现和空列表一样的问题。
      猜你喜欢
      • 2020-10-14
      • 2018-11-11
      • 1970-01-01
      • 2019-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-17
      相关资源
      最近更新 更多