令人困惑的python继承

时间:2013-01-12 08:03:36

标签: python inheritance


class BaseA(object):
    authors = ['a', 'b']
    author_list = authors

class BaseB(object):
    authors = ['a', 'b']

    def __init__(self, *arg, **kwargs):
        self.author_list = self.authors

class ChildA(BaseA):
    authors = ['c', 'd']

class ChildB(BaseB):
    authors = ['c', 'd']

child_a = ChildA()
child_b = ChildB()
print(child_a.author_list)
print(child_b.author_list)
>>> ['a', 'b']
>>> ['c', 'd']

代码的不同之处是什么?为什么我会得到不同的结果?

我很困惑为什么父author_list属性不会被覆盖。

你能告诉我python继承的原理吗?

4 个答案:

答案 0 :(得分:3)

class块中的材质是类本身的一部分,在定义类时,执行一次__init__中的材质是每个实例,每次实例化该类时,每个实例执行一次

在第一个示例(BaseA)中,您创建了一个类属性authors,然后创建另一个指向相同值的属性author_list。这就对了。没有其他事情发生过。 ChildABaseA继承的事实不会导致author_list = authors重新执行。 author_list已经结束,并且在BaseA被定义后完成。

在第二个示例(BaseB)中,您创建了一个类属性authors。然后在__init__中创建一个指向相同值的新实例属性。由于您在__init__中执行此操作,因此会为每个实例重新执行此操作。因此,当您实例化BaseB时,它会获取新属性。

请注意,您正在检查实例child_achild_b上的属性。如果您在课程(ChildA.author_listChildB.author_list)上查看它们,您会发现它们都具有相同的值(['a', 'b'])。因为您在ChildB中的操作发生在__init__中,所以只有在您实际实例化该类时它才会生效。

答案 1 :(得分:0)

不同之处在于,在第二个示例中,在创建对象实例时设置了author_list

当您定义类BaseA时,您定义了类成员author_list,那就是这样,所以当您创建ChildA的实例时,author_list没有任何事情发生。它只是遗传。

定义BaseB时,没有成员author_list。当创建BaseB的实例时,将其创建为实例变量。因此,当您创建ChildB的实例时,会发生相同的事情,但由于authors已重新定义,因此它将使用新值authors

答案 2 :(得分:0)

在 BaseB __init__ 函数中,您调用的是 Child 的作者,而不是 Parent 的作者。 如果您想调用父母的作者,您可以使用 BaseB.authors 而不是 self.authors

class BaseA(object):
    authors = ['a', 'b']
    author_list = authors

class BaseB(object):
    authors = ['a', 'b']

    def __init__(self, *arg, **kwargs):
        self.author_list = BaseB.authors

class ChildA(BaseA):
    authors = ['c', 'd']

class ChildB(BaseB):
    authors = ['c', 'd']

child_a = ChildA()
child_b = ChildB()
print(child_a.author_list)
print(child_b.author_list)
>>> ['a', 'b']
>>> ['a', 'b']

如果您将连接 ParentB 和 ChildB 的作者,那么您将同时使用 BaseB.authorsself.authors

class BaseA(object):
    authors = ['a', 'b']
    author_list = authors

class BaseB(object):
    authors = ['a', 'b']

    def __init__(self, *arg, **kwargs):
        self.author_list = BaseB.authors + self.authors

class ChildA(BaseA):
    authors = ['c', 'd']

class ChildB(BaseB):
    authors = ['c', 'd']

child_a = ChildA()
child_b = ChildB()
print(child_a.author_list)
print(child_b.author_list)
>>> ['a', 'b']
>>> ['a', 'b', 'c', 'd']

覆盖

class BaseA(object):
    authors = ['a', 'b']
    author_list = authors

class BaseB(object):
    authors = ['a', 'b']

    def __init__(self, *arg, **kwargs):
        self.author_list = self.authors

class ChildA(BaseA):
    authors = ['c', 'd']
    def __init__(self, *arg, **kwargs):
        self.author_list = self.authors

class ChildB(BaseB):
    authors = ['c', 'd']

child_a = ChildA()
child_b = ChildB()
print(child_a.author_list)
print(child_b.author_list)
>>> ['c', 'd']
>>> ['c', 'd']

答案 3 :(得分:0)

推荐的 Python 代码编写方式:

class BaseA(object):
    def __init__(self):
        self.authors = ['a', 'b']

class BaseB(object):
    def __init__(self):
        self.authors = ['a', 'b']

class ChildA(BaseA):
    def __init__(self):
        self.authors = ['c', 'd']
    
class ChildB(BaseB):
    def __init__(self):
        self.authors = ['c', 'd']


child_a = ChildA()
child_b = ChildB()
print(child_a.authors)
print(child_b.authors)
>>> ['c', 'd']
>>> ['c', 'd']

推荐的调用超类(基父类)的方法:

class BaseA(object):
    def __init__(self):
        self.authors = ['a', 'b']

class BaseB(object):
    def __init__(self):
        self.authors = ['a', 'b']

class ChildA(BaseA):
    def __init__(self):
        self.authors = ['c', 'd']
        super().__init__()
    
class ChildB(BaseB):
    def __init__(self):
        self.authors = ['c', 'd']
        BaseB.__init__(self)


child_a = ChildA()
child_b = ChildB()
print(child_a.authors)
print(child_b.authors)
>>> ['a', 'b']
>>> ['a', 'b']

__init__ (__init_) 末尾使用一个下划线的深奥超类调用:

class BaseA(object):
    def __init__(self):
        self.authors = ['a', 'b']

class BaseB(object):
    def __init__(self):
        self.authors = ['a', 'b']

class ChildA(BaseA):
    def __init_(self):
        self.authors = ['c', 'd']
    
class ChildB(BaseB):
    def __init_(self):
        self.authors = ['c', 'd']


child_a = ChildA()
child_b = ChildB()
print(child_a.authors)
print(child_b.authors)
>>> ['a', 'b']
>>> ['a', 'b']

注意

使用深奥的超类调用会导致无法访问子变量!

对子类(子类)中方法的访问仍然可以访问,但对子类(子类)中变量的所有访问都将完全丢失。