Python 编程要点 -- 类方法,静态方法,实例方法,mro机制
来源:互联网 发布:python分布式爬虫系统 编辑:程序博客网 时间:2024/05/21 04:00
Python 类方法,静态方法,实例方法
类方法,静态方法,实例方法都可以通过类名和实例对象访问,如下:
需要注意点一点是类名访问实例方法的时候必须传递实例对象。
注意:函数 只能由类名访问(Python3),Python2不能访问。
注意:申明静态方法使用@staticmethod 并且不用加类名或者实例对象作为参数
注意:申明类方法使用@classmethod 并且需要加上cls作为方法参数
class A(object): @classmethod def cls_func(cls): print "classmethod" @staticmethod def static_func(): print("staticmethod") def instance_func(self): print("instance_func") def common_func(): print("common func")a = A()a.cls_func()a.static_func()a.instance_func()A.cls_func()A.static_func()A.instance_func(a)#Error python2 中类名不能访问函数,但是Python3可以访问#A.common_func()#Error Python2/3中都不能使用实例访问函数#a.common_func()>>classmethodstaticmethodinstance_funcclassmethodstaticmethodinstance_funccommon func
子类中访问父类的方法,以及多重继承的问题
在python中子类访问父类的方法有两种方式:
1.使用类名调用类的方法:
class A(object): def __init__(self): print("Call A __init__!")class B(A): def __init__(self): print("Call B __init__!") A.__init__(self)b = B()>>Call B __init__!Call A __init__!
2.使用super调用父类的方法:
class A(object): def __init__(self): print("Call A __init__!")class B(A): def __init__(self): print("Call B __init__!") super(B, self).__init__()b = B()>>Call B __init__!Call A __init__!
方法一更直观。推荐使用方法一进行父类的初始化。
注意!注意!注意!这里纠正一下:有的地方说方法二可以一次初始化所有超类,该说法是错误的。super并不是像Java或者其他语言一样调用所有父类的构造方法,它是调用的__class__.mro()
的下一个类调用构造方法 如下:
下面的函数并不会调用B类的构造函数,因为__class__.mro()
指向的下一个类是A。
class A(object): def __init__(self, age=1): print("A __init__!") self.age = ageclass B(object): def __init__(self, name=""): print("B __init__!") self.name = nameclass C(A,B): def __init__(self): print("C __init__!") super(C, self).__init__()c = C()>>C __init__!A __init__![<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
就算调用两次super也不会初始化B的构造函数,如下:
反而它只是调用了两次A类的构造函数而已。
class A(object): def __init__(self, age=1): print("A __init__!") self.age = ageclass B(object): def __init__(self, name=""): print("B __init__!") self.name = nameclass C(A,B): def __init__(self): print("C __init__!") super(C, self).__init__() super(C, self).__init__()c = C()>>C __init__!A __init__!A __init__![<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
下面列举一个更加复杂的例子来说明:
如果是想当然以为super是调用父类的构造函数那么输出的顺序应该是
>>B __init__!A __init__!A leaving!B leaving!C __init__!A __init__!A leaving!C leaving !
然而情况是:当调用D的初始化函数时按照D类的mro()顺序来选择下一个类的初始化。
这里还可以看出如果你没有写__init__
函数,那么python默认的方式是通过super初始化父类
class A(object): def __init__(self, age=0): print("A __init__!") self.age = age print("A leaving!")class B(A): def __init__(self, name=""): print("B __init__!") super(B, self).__init__() self.name = name print("B leaving!")class C(A): def __init__(self): print("C __init__!") super(C, self).__init__() print("C leaving !")class D(B, C): passd = D() print(d.__class__.mro())>>B __init__!C __init__!A __init__!A leaving!C leaving !B leaving![<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>]
结论是:当你的程序里面含有多重继承存在的时候千万要注意尽量避免使用super的方式,而应该直接使用类名初始化的方式,多写几行代码比出错来的划算!上面的例子改写为方法一的方式如下:
class A(object): def __init__(self, age=0): print("A __init__!") self.age = age print("A leaving!")class B(A): def __init__(self, name=""): print("B __init__!") A.__init__(self, age=12) self.name = name print("B leaving!")class C(A): def __init__(self): print("C __init__!") A.__init__(self, age=14) print("C leaving !")class D(B, C): def __init__(self): print("D __init__!") B.__init__(self) C.__init__(self) print("D leaving!")d = D() >>D __init__!B __init__!A __init__!A leaving!B leaving!C __init__!A __init__!A leaving!C leaving !D leaving!
Python mro 的顺序问题
首先mro是按照深度优先的计算方式,重复类只保留最后一个这是什么意思呢?就拿上面的例子来说深度优先的原则的话就应该是[D, B, A, object, C, A, object] 这样一个顺序,但是重复类只保留最后一个的原则决定了它应该是[D, B, C, A, object]这样的。所以这样就很好的理解了super为什么会表现出那样的方式。
下面再给出一个例子说明:
class A(object): def __init__(self, age=0): print("A __init__!") self.age = age print("A leaving!") def func(self): print("A func call!")class B(A): def __init__(self, name=""): print("B __init__!") A.__init__(self, age=12) self.name = name print("B leaving!")class C(A): def __init__(self): print("C __init__!") A.__init__(self, age=14) print("C leaving !") def func(self): print("C func call!")class D(B, C): def __init__(self): print("D __init__!") B.__init__(self) C.__init__(self) print("D leaving!")d = D()d.func()>>D __init__!B __init__!A __init__!A leaving!B leaving!C __init__!A __init__!A leaving!C leaving !D leaving!C func call!
以上程序的输出是C func 被调用了,也证实了mro的顺序规则。
- Python 编程要点 -- 类方法,静态方法,实例方法,mro机制
- python类方法、实例方法、静态方法
- Python 静态方法 类方法 实例方法
- python实例方法,静态方法,类方法
- Python:类方法、静态方法、实例方法
- python实例方法、静态方法、类方法
- python类方法 实例方法 静态方法
- python实例方法、类方法、静态方法
- python初学 类方法 实例方法 静态
- python 方法、实例方法、静态方法、类方法
- Python学习-方法解析顺序(MRO)
- Python的方法解析顺序(MRO)
- Python的方法解析顺序(MRO)
- Python的方法解析顺序(MRO)
- Python的方法解析顺序(MRO)
- python类实例方法,类方法,类静态方法
- python 类方法、类实例方法、静态方法
- python 类的实例方法,静态方法,类方法辨析
- 算法机考模拟题1001.会议安排
- SpringBoot-06的全局异常捕捉
- 一条SQL语句查出每个班的及格人数和不及格人数,格式为:class,及格人数,不及格人数(score>=60为及格)
- 用一台机器(不需要虚拟机)刷dropbox容量的方法
- 一个屌丝程序猿的人生(六)
- Python 编程要点 -- 类方法,静态方法,实例方法,mro机制
- [LeetCode] 508. Most Frequent Subtree Sum
- gerrit权限控制
- phpStorm快捷键
- PhxSQL设计与实现
- Java基础语法
- 微信支付接入流程——APP支付
- JZ2440 ADC和触摸屏学习笔记
- Openstack Newton虚拟机迁移计算节点补充配置