Python类成员初始化 [英] Python Class Members Initialization

查看:202
本文介绍了Python类成员初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚在Python中打过一个错误。它是那些蠢的新手bug之一,但它让我思考Python的机制(我是一个长期的C ++程序员,Python的新手)。我将展示buggy代码,并解释我做了什么来解决它,然后我有几个问题...



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

  A类:
dict1 = {}

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

def print_stuff
print(self.dict1)

使用此代码的类是B类: p>

  class B:

def do_something_with_a1(self):
a_instance = A $ b 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 ',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()$ b $注意,每次调用 do_something_with_aX()都会初始化一个新的clean类A的实例,并在添加之前和之后打印字典。



错误(如果你还没有想到它) p>

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

在类A的第二个初始化中,字典不为空,但是从最后一次初始化的内容开始,等等。我希望他们开始新鲜。



解决这个bug显然是添加了:

  self.dict1 = {} 

> __ init __ 类A的构造函数。但是,这使我很奇怪:


  1. dict1 = {}在dict1声明的点初始化(类A中的第一行)?

  2. 导致从最后一次初始化复制引用的实例化机制是什么?

  3. 如果在构造函数(或任何其他数据成员)中添加self.dict1 = {},它如何影响先前初始化实例的字典成员?






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

解决方案

文档,Python类的标准行为。



正如你最初所做的那样声明一个 __ init __ 外部的dict声明一个类级别的变量。它只创建一次,只要创建新对象,它将重用这个相同的dict。要创建实例变量,请在 __ init __ 中使用 self 声明它们;它很简单。


I have just recently battled a bug in Python. It was one of those silly newbie bugs, but it got me thinking about the mechanisms of Python (I'm a long time C++ programmer, new to Python). I will lay out the buggy code and explain what I did to fix it, and then I have a couple of questions...

The scenario: I have a class called A, that has a dictionary data member, following is its code (this is simplification of course):

class A:
    dict1={}

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

    def print_stuff(self):
        print(self.dict1)

The class using this code is class 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()

Notice that every call to do_something_with_aX() initializes a new "clean" instance of class A, and prints the dictionary before and after the addition.

The bug (in case you haven't figured it out yet):

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

In the second initialization of class A, the dictionaries are not empty, but start with the contents of the last initialization, and so forth. I expected them to start "fresh".

What solves this "bug" is obviously adding:

self.dict1 = {}

In the __init__ constructor of class A. However, that made me wonder:

  1. What is the meaning of the "dict1 = {}" initialization at the point of dict1's declaration (first line in class A)? It is meaningless?
  2. What's the mechanism of instantiation that causes copying the reference from the last initialization?
  3. If I add "self.dict1 = {}" in the constructor (or any other data member), how does it not affect the dictionary member of previously initialized instances?


EDIT: Following the answers I now understand that by declaring a data member and not referring to it in the __init__ or somewhere else as self.dict1, I'm practically defining what's called in C++/Java a static data member. By calling it self.dict1 I'm making it "instance-bound".

解决方案

What you keep referring to as a bug is the documented, standard behavior of Python classes.

Declaring a dict outside of __init__ as you initially did is declaring a class-level variable. It is only created once at first, whenever you create new objects it will reuse this same dict. To create instance variables, you declare them with self in __init__; its as simple as that.

这篇关于Python类成员初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆