博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python3 super().__init__()
阅读量:5338 次
发布时间:2019-06-15

本文共 2856 字,大约阅读时间需要 9 分钟。

父类不会自动调用__init__方法

class A:    def __init__(self):        A = 'A'        self.a = 'a'        print('init A')        class B(A):    def __init__(self):        self.b = 'b'        print('init B')b = B()print(b.A)print(b.a)
init BA---------------------------------------------------------------------------AttributeError                            Traceback (most recent call last)
in
1 b = B() 2 print(b.A)----> 3 print(b.a)AttributeError: 'B' object has no attribute 'a'

子类继承父类,子类实例化只会调用自己的构造方法,父类的构造方法不会调用,或者说子类重写了父类的构造方法,所以父类在构造方法中定义的默认属性也无法继承。

实例变量不能继承不是Python继承有问题,上面在class A中定义了一个类变量A就被成功继承下来了,python类中的所有最外层类变量,类方法,静态方法,实例方法该继承都会继承,不过实例变量是定义在__init__构造方法中的,虽然__init__会在实例化时自动执行(不管是父类还是子类),但子类重写了父类方法,所以父类构造没有执行,只是执行了子类构造。不然看下面一个例子:

class E(A):    passe = E()print(e.a)
init Aa

如果子类没有重写父类方法那么父类构造还是自动执行了。所以总的来说父类构造没有执行的原因是**子类重写了父类的__init__方法**

使用super().__init__()手动执行父类的构造方法

如果要手动执行, 首先绝不能这样:

class B(A):    def __init__(self):        self.__init__()        self.b = 'b'        print('init B')b = B()print(b.A)print(b.a)
---------------------------------------------------------------------------RecursionError                            Traceback (most recent call last)
in
----> 1 b = B() 2 print(b.A) 3 print(b.a)
in __init__(self) 7 class B(A): 8 def __init__(self):----> 9 self.__init__() 10 self.b = 'b' 11 print('init B')... last 1 frames repeated, from the frame below ...
in __init__(self) 7 class B(A): 8 def __init__(self):----> 9 self.__init__() 10 self.b = 'b' 11 print('init B')RecursionError: maximum recursion depth exceeded

这样做的后果是会无限递归调用子类自己的__init__

不过可以手动指定父类类名进行调用,比如下面这样:

class B(A):    def __init__(self):        A.__init__(self)        self.b = 'b'        print('init B')b = B()print(b.A)print(b.a)
init Ainit BAa

这样做是可以成功的,缺点就是太累了,在多继承环境下我们需要指定每一个父类进行调用,比如下面这样

class B(A):    def __init__(self):        A.__init__(self)        self.b = 'b'        print('init B')    class C(A):    def __init__(self):        self.c = 'c'        print('init C')        class D(B,C):    def __init__(self):        B.__init__(self)        C.__init__(self)        self.d = 'd'        print('init D')d = D()print(d.b)print(d.c)
init Ainit Binit Cinit Dbc

显然B需要调A,D需要调用B和C,显然不符合python的优雅风格

super().__init__的好处就是统一进行所有父类构造方法的调用,调用的先后根据类型的mro顺序决定,将自动调用所有父类的构造方法
我们这里只关注直系父类,因为对于祖父级别的类构造方法是否调用取决于父类中是否重写了祖父的构造方法,只要在继承的父类中有一个父类重写了祖父的构造方法,那么祖父的构造方法也不会被调用。
我们可以根据<class>.mro()查看类型的MRO表

print(D.mro())[
,
,
,
,
]

super().__init__()是python3中简化后的方法,功能和super(self.__class__, self).__init__()一样

转载于:https://www.cnblogs.com/Peter2014/p/10844204.html

你可能感兴趣的文章
cocos2dx - 制作纵版射击游戏:喵星战争 (五)
查看>>
一. python基础
查看>>
字符流
查看>>
文本处理三剑客之gawk
查看>>
测试与代码质量
查看>>
Eclipse Access Restriction
查看>>
行间距
查看>>
20145305 《网络对抗》Web基础
查看>>
GDB调试器使用总结
查看>>
linux 常用命令
查看>>
雷林鹏分享:Ruby CGI Cookies
查看>>
python---用链表结构实现有序和无序列表的几个功能
查看>>
学习杂记(如何让两个div在同一行)
查看>>
JAVA IO类
查看>>
Leetcode: 从中序与后序遍历序列构造二叉树
查看>>
福建工程学院第十四届ACM校赛B题题解
查看>>
mysql---左连接、右连接、内连接之间的区别与联系
查看>>
IT204 Homework Assignment 2
查看>>
Windows平台配置5.7+版本MySQL数据库服务
查看>>
基础 Linux 命令速查清单
查看>>