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

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

问题描述

我最近刚与 Python 中的一个错误作斗争.这是那些愚蠢的新手错误之一,但它让我想到了 Python 的机制(我是 C++ 的长期程序员,Python 新手).我将列出有问题的代码并解释我做了什么来修复它,然后我有几个问题......

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

A 类:dict1={}def add_stuff_to_1(self, k, v):self.dict1[k]=vdef print_stuff(self):打印(self.dict1)

使用这个代码的类是B类:

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()打印(" - -")self.do_something_with_a2()打印(" - -")self.do_something_with_a3()

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

错误(以防你还没有弄清楚):

<预><代码>>>>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类的第二次初始化中,字典不是空的,而是从上次初始化的内容开始,以此类推.我希望他们开始新鲜".

解决这个错误"的显然是添加:

self.dict1 = {}

在 A 类的 __init__ 构造函数中.然而,这让我感到奇怪:

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

<小时>

按照答案,我现在明白通过声明一个数据成员而不是在 __init__ 或其他地方作为 self.dict1 引用它,我实际上是在定义 C++/Java 一个静态数据成员.通过将其称为 self.dict1,我将其设置为实例绑定".

解决方案

你一直提到的 bug 是 已记录,Python 类的标准行为.

像最初那样在 __init__ 之外声明一个 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天全站免登陆