在中我们介绍了一些基础的类定义和使用方式,我们这里用OOP的原则对其进行重新审视,并且补充没有说到的部分。
封装
关于封装,在中我们介绍了简单的封装方式,即如何用前缀_
或__
来实现类似的访问修饰符的作用。
但有一点我们没有说明,即如何实现类方法。
我们知道,类方法和对象方法最大的不同是不依赖于对象的属性,当然也不存在对象指针或引用。
class sampleCls:
def classMethod(cls):
print(cls)
print("this is a class method")
def objMethod(self):
print(self)
print("this is a object method")
a = sampleCls()
a.objMethod()
sampleCls.classMethod()
# <__main__.sampleCls object at 0x000001F963AF88E0>
# this is a object method
# <class '__main__.sampleCls'>
# this is a class method
从上边我们可以看到,通过使用函数修饰符classmethod
,我们定义了一个类方法classMethod
。
而最终的打印结果也表明了这两个方法持有的引用分别是对象和类。
继承
在继承上,Python与传统编程语言有很大不同,它支持多继承。
我们来看一个稍显复杂的例子:
class A:
def __init__(self):
print("A.__init__()")
class B(A):
def __init__(self):
super().__init__()
print("B.__init__()")
class C(A):
def __init__(self):
super().__init__()
print("C.__init__()")
class D(B,C):
def __init__(self):
super().__init__()
print("D.__init__()")
d = D()
print(D.__mro__)
# A.__init__()
# C.__init__()
# B.__init__()
# D.__init__()
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
从输出我们可以观察到,这个继承关系创建过程是A>C>B>D,而且这其中虽然C和B都继承了A,但解释器很聪明,只创建了一次A。
我们这里除了在构造函数中输出以观察构建过程,还通过D.__mro__
输出了一个继承关系链。
关于MRO,一书是这么解释的:
对于你定义的每一个类,Python会计算出一个所谓的方法解析顺序(MRO)列表。 这个MRO列表就是一个简单的所有基类的线性顺序表。
我画了一个简单的类图来说明上边的继承关系和MRO检索顺序:
关于MRO检索顺序,《Python Cookbook》是这么说的:
子类会先于父类被检查
多个父类会根据它们在列表中的顺序被检查
如果对下一个类存在两个合法的选择,选择第一个父类
我们这个例子已经显得很混乱了,如果遇到继承层级更复杂的局面,要理清继承链的难度可想而知。我的建议是使用clsName.__mro__
查看解释器实际的继承链,再结合UML图理清继承关系。
至于这么做的必要性,如果你的继承链上有同名函数互相覆盖,那理清继承链才能确切知道哪个会覆盖哪个。
这种问题在算法中被称作“菱形问题”,在中有详细的说明。
多态
说到多态,其核心内容肯定是抽象类和接口,而在Python中这是一回事。
from abc import ABCMeta, abstractmethod
class Base(metaclass=ABCMeta):
def fly(self):
'''这是一个抽象方法'''
pass
class SubBase(Base):
def fly(self):
print("I can fly")
# base = Base() 会报错,因为抽象类不能实例化
base = SubBase()
base.fly()
# I can fly
借助abc
这里通过指定元类
metaclass=ABCMeta
的方式已经过时,最新的方式更为简洁,只要继承abc.ABC
类即可。关于抽象基类的更深入内容,可以阅读。
这里
metaclass=ABCMeta
属于元编程的范围,想深入了解可以阅读。
关于Python中类的更多内容,可以阅读《Python Cookbook》的。
本系列文章的代码都存放在Github项目:。
文章评论