Python 父类有一个支持实例

Python 父类有一个支持实例,python,inheritance,Python,Inheritance,假设我有以下代码: class ParentClass(): myList=[] 定义初始化(自): 打印(“父类构造函数”) 儿童班(家长班): 定义初始化(自): 打印(“子构造函数”) def添加元素(自身,项目): self.myList.append(项) 打印(f“按子项A添加项,当前长度:{len(self.myList)}”) 儿童B类(家长类): 定义初始化(自): 打印(“子B构造函数”) def添加元素(自身,项目): self.myList.append(项) 打印(f“

假设我有以下代码:

class ParentClass():
myList=[]
定义初始化(自):
打印(“父类构造函数”)
儿童班(家长班):
定义初始化(自):
打印(“子构造函数”)
def添加元素(自身,项目):
self.myList.append(项)
打印(f“按子项A添加项,当前长度:{len(self.myList)}”)
儿童B类(家长类):
定义初始化(自):
打印(“子B构造函数”)
def添加元素(自身,项目):
self.myList.append(项)
打印(f“按子项B添加项,当前长度:{len(self.myList)}”)
a=ChildA()
a、 增加要素(1)
a、 增加要素(1)
b=ChildB()
b、 增加要素(1)
当我运行它(Python 3.9.3)时,我得到以下输出:

Child A constructor
Added item by Child A, current length: 1
Added item by Child A, current length: 2
Child B constructor
Added item by Child B, current length: 3
这表明子类从中继承的父类有一个备份实例,因为我没有在构造函数中将
myList
显式设置为
[]
,所以它使用相同的备份内存,即使对于两个不同的子类也是如此

  • 这个假设正确吗
  • 这种设计的有效用途是什么?当我第一次发现这种行为时,我认为这可能是一个语言错误,但我觉得这不太可能
  • 我通过在父构造函数中将
    myList
    显式设置为
    []
    来解决这个问题,但我对这个行为感到困惑,因为它不是我所期望的行为(我希望在第一次调用
    ChildB
    之后
    myList
    的长度为1)

    我只是通过在父构造函数中将myList显式设置为[]来解决这个问题,但我对这个行为感到困惑,因为它不是我所期望的行为

    没错。您所做的是在类本身上定义变量,而不是在类的实例上定义变量。定义实例变量的正确方法是在构造函数中

    class ParentClass():
    
        def __init__(self):
            print("Parent class constructor")
            self.myList = []
    

    如果要避免这种情况,可以在每个子类的
    \uuuuu init\uuuu
    方法中声明列表:

    class ParentClass():
        
        def __init__(self):
            self.myList = []
            print("Parent class constructor")
    
    class ChildA(ParentClass):
        def __init__(self):
            self.myList=[]
            print("Child A constructor")
    
        def add_elem(self, item):
            self.myList.append(item)
            print(f"Added item by Child A, current length: {len(self.myList)}")
    
    class ChildB(ParentClass):
        def __init__(self):
            self.myList=[]
            print("Child B constructor")
    
        def add_elem(self, item):
            self.myList.append(item)
            print(f"Added item by Child B, current length: {len(self.myList)}")
            
    
    a = ChildA()
    a.add_elem(1)
    a.add_elem(1)
    
    b = ChildB()
    b.add_elem(1)
    
    输出:

    Child A constructor
    Added item by Child A, current length: 1
    Added item by Child A, current length: 2
    Child B constructor
    Added item by Child B, current length: 1
    

    是的,只有一个
    myList
    你忘了调用父构造函数,这不会有帮助:父构造函数永远不会被调用。我只会做
    super()。\uuuu init\uuuuu(self)
    或者在子类中调用它。@Silvio Mayolo这很有意义,谢谢你澄清这一点!我忘了区分类变量和实例变量。