【问题标题】:Python constructor and default value [duplicate]Python构造函数和默认值[重复]
【发布时间】:2011-06-18 00:38:16
【问题描述】:

不知何故,在下面的 Node 类中,wordListadjacencyList 变量在所有 Node 实例之间共享。

>>> class Node:
...     def __init__(self, wordList = [], adjacencyList = []):
...         self.wordList = wordList
...         self.adjacencyList = adjacencyList
... 
>>> a = Node()
>>> b = Node()
>>> a.wordList.append("hahaha")
>>> b.wordList
['hahaha']
>>> b.adjacencyList.append("hoho")
>>> a.adjacencyList
['hoho']

有什么方法可以让构造函数参数继续使用默认值(在这种情况下为空列表),但同时让ab 拥有自己的wordListadjacencyList 变量?

我正在使用 python 3.1.2。

【问题讨论】:

    标签: python constructor default-value


    【解决方案1】:

    可变的默认参数通常不会做你想做的事。相反,试试这个:

    class Node:
         def __init__(self, wordList=None, adjacencyList=None):
            if wordList is None:
                self.wordList = []
            else:
                 self.wordList = wordList 
            if adjacencyList is None:
                self.adjacencyList = []
            else:
                 self.adjacencyList = adjacencyList 
    

    【讨论】:

    • 这些也可以是单行代码:self.wordList = wordList if wordList is not None else [],或者,安全性稍差一点,self.wordList = wordList or []
    • 这被认为是 Pythonic 的方式,但我更喜欢 krousey 的方式,因为“特殊情况还不够特殊”。
    • @markdsievers 除了None 之外的许多东西都会评估为False(例如False0""{}()、指定__nonzero__() 的对象)。前者是特定的:None 是唯一触发默认为[] 的特殊对象。后者会将任何 false-y 对象替换为 []
    • Michael J. Barber 的贡献是正确的 - 但没有提供任何解释。这种行为的原因是默认参数是在函数定义时绑定的,而不是运行时。见stackoverflow.com/questions/1132941/…
    • 那么,这是一个错误吗?这种行为非常违反直觉。
    【解决方案2】:
    class Node:
        def __init__(self, wordList=None adjacencyList=None):
            self.wordList = wordList or []
            self.adjacencyList = adjacencyList or []
    

    【讨论】:

      【解决方案3】:

      让我们来说明这里发生了什么:

      Python 3.1.2 (r312:79147, Sep 27 2010, 09:45:41) 
      [GCC 4.4.3] on linux2
      Type "help", "copyright", "credits" or "license" for more information.
      >>> class Foo:
      ...     def __init__(self, x=[]):
      ...         x.append(1)
      ... 
      >>> Foo.__init__.__defaults__
      ([],)
      >>> f = Foo()
      >>> Foo.__init__.__defaults__
      ([1],)
      >>> f2 = Foo()
      >>> Foo.__init__.__defaults__
      ([1, 1],)
      

      您可以看到默认参数存储在一个元组中,该元组是相关函数的一个属性。这实际上与所讨论的类无关,适用于任何功能。在 python 2 中,该属性将为func.func_defaults

      正如其他发帖者所指出的,您可能希望使用None 作为标记值,​​并为每个实例提供它自己的列表。

      【讨论】:

        【解决方案4】:

        我会尝试:

        self.wordList = list(wordList)
        

        强制它复制而不是引用同一个对象。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-01-27
          • 2020-05-14
          • 1970-01-01
          • 2014-05-19
          • 2012-06-22
          • 1970-01-01
          • 2013-03-16
          • 2016-09-05
          相关资源
          最近更新 更多