Python类成员初始化

Roe*_*ler 41 python initialization class

我最近刚刚在Python中遇到了一个bug.这是一个愚蠢的新手错误,但它让我思考Python的机制(我是一个长期的C++程序员,Python的新手).我将列出有缺陷的代码并解释我做了什么来解决它,然后我有几个问题......

场景:我有一个名为A的类,它有一个字典数据成员,下面是它的代码(这当然是简化):

class A:
    dict1={}

    def add_stuff_to_1(self, k, v):
        self.dict1[k]=v

    def print_stuff(self):
        print(self.dict1)
Run Code Online (Sandbox Code Playgroud)

使用此代码的类是B类:

class B:

    def do_something_with_a1(self):
        a_instance = A()
        a_instance.print_stuff()        
        a_instance.add_stuff_to_1('a', 1)
        a_instance.add_stuff_to_1('b', 2)    
        a_instance.print_stuff()

    def do_something_with_a2(self):
        a_instance = A()    
        a_instance.print_stuff()            
        a_instance.add_stuff_to_1('c', 1)
        a_instance.add_stuff_to_1('d', 2)    
        a_instance.print_stuff()

    def do_something_with_a3(self):
        a_instance = A()    
        a_instance.print_stuff()            
        a_instance.add_stuff_to_1('e', 1)
        a_instance.add_stuff_to_1('f', 2)    
        a_instance.print_stuff()

    def __init__(self):
        self.do_something_with_a1()
        print("---")
        self.do_something_with_a2()
        print("---")
        self.do_something_with_a3()
Run Code Online (Sandbox Code Playgroud)

请注意,每次调用都会do_something_with_aX()初始化A类的新"干净"实例,并在添加之前和之后打印字典.

这个bug(如果你还没弄明白的话):

>>> b_instance = B()
{}
{'a': 1, 'b': 2}
---
{'a': 1, 'b': 2}
{'a': 1, 'c': 1, 'b': 2, 'd': 2}
---
{'a': 1, 'c': 1, 'b': 2, 'd': 2}
{'a': 1, 'c': 1, 'b': 2, 'e': 1, 'd': 2, 'f': 2}
Run Code Online (Sandbox Code Playgroud)

在类A的第二次初始化中,字典不是空的,而是从最后一次初始化的内容开始,依此类推.我希望他们开始"新鲜".

解决这个"错误"的原因显然是:

self.dict1 = {}
Run Code Online (Sandbox Code Playgroud)

__init__A类的构造函数中.然而,这让我想知道:

  1. dict1声明点(A类中的第一行)的"dict1 = {}"初始化是什么意思?这没意义?
  2. 实例化的机制是什么导致从上次初始化复制引用?
  3. 如果我在构造函数(或任何其他数据成员)中添加"self.dict1 = {}",它如何不影响以前初始化的实例的字典成员?

编辑:按照答案我现在明白,通过声明一个数据成员而不是在__init__其他地方或者其他地方引用它作为self.dict1,我实际上定义了在C++/Java中调用的静态数据成员.通过调用它self.dict1我正在使它"实例绑定".

Pao*_*ino 53

您一直称之为错误的是Python类的文档化标准行为.

__init__最初在你之外声明一个字典是声明一个类级变量.它最初只创建一次,每当你创建新对象时,它将重用这个相同的dict.要创建实例变量,请使用selfin 声明它们__init__; 就这么简单.

  • 我没有说这是一个Python bug,我说这是我的错误...当一个程序员对文档做了一些事情时,它仍然是一个bug(如我所提到的那样愚蠢).我的问题是关于触发这种"记录的,标准行为"的机制 - 我想了解内幕的内容.谢谢.特别是我的第一个问题,我想了解声明初始化是否无用. (14认同)
  • 这不是无用的; 如果你想要一个变量来保存实例,你会使用它.你的问题是,当你执行x = A()时,只执行__init__代码.类变量仍然存在. (5认同)
  • 好的,只要声明不在__init__中,它就与C ++中的“静态”数据成员相同,并且“ __init__”中的声明将其从静态更改为实例绑定?现在很清楚,谢谢。 (2认同)