1. 继承关系
(1)继承简介:继承是一种创建新类的方式,新建的类可称为子类或派生类,父类可称为基类或超类。python中的继承关系有单继承和多继承,单继承语法为:class 子类名(父类名): 内容体
;多继承语法为:class 子类名(父类1,父类2,...,父类N):内容体
。其中多继承的优先级为从左到右,即父类1的优先级最高。单继承和多继承的例子如下所示:
class Parent1:
pass
class Parent2:
pass
class Parent3:
pass
class Sub1(Parent1):
"""单继承:子类Sub1只继承了父类Parent1"""
pass
class Sub2(Parent1, Parent2, Parent3):
"""多继承:子类Sub2分别继承了Parent1, Parent2, Parent3"""
pass
# __bases__属性可以查看该类的所有直接父类,返回所有直接父类组成的元组。
print(f"子类Sub1的直接父类有:{Sub1.__bases__}")
print(f"子类Sub2的直接父类有:{Sub2.__bases__}")
输出:
子类Sub1的直接父类有:(<class '__main__.Parent1'>,)
子类Sub2的直接父类有:(<class '__main__.Parent1'>, <class '__main__.Parent2'>, <class '__main__.Parent3'>)
(2)object类:object类是所有类的父类,所有的内置类型(像int、float、str、list等等)、用户自定义的类都直接或间接地继承于object类。如果该类没有继承任何类,默认继承object类。代码如下所示:
class Parent:
pass
class Sub(object):
pass
print(f"parent的直接父类有:{Parent.__bases__}")
print(f"Sub的直接父类有:{Sub.__bases__}")
输出:
parent的直接父类有:(<class 'object'>,)
Sub的直接父类有:(<class 'object'>,)
(3)常见的属性:
__class__
属性:该属性和type()
函数一样,都是查询对象的数据类型;__dict__
属性:查看对象内部所有属性名和属性值组成的字典,可以通过类名或者实例对象来调用__dict__
属性。用类名直接调用__dict__
,会输出类中所有类属性组成的字典;而使用类的实例对象调用__dict__
,会输出类中所有实例属性组成的字典。__bases__
属性:用来查看该类的所有直接父类,返回所有直接父类组成的元组。__mro__
(Method Resolution Order–方法解析顺序)表:返回多继承的调用顺序。__class__
属性和__dict__
属性的代码如下:
class Person:
name = "AAA" # 类属性
age = 11 # 类属性
def __init__(self,_name: str, _age: int) -> None:
self._name = _name # 实例属性
self._age = _age # 实例属性
p = Person("zhangsan", 18)
print(f"实例对象p的类型为:{p.__class__}")
print(f"实例对象p的类型为:{type(p)}")
print(f"类属性组成的字典:{Person.__dict__}")
print(f"实例属性组成的字典:{p.__dict__}")
输出:
实例对象p的类型为:<class '__main__.Person'>
实例对象p的类型为:<class '__main__.Person'>
类属性组成的字典:{'__module__': '__main__', 'name': 'AAA', 'age': 11,
'__init__': <function Person.__init__ at 0x000002C838F0DAF8>,
'__dict__': <attribute '__dict__' of 'Person' objects>,
'__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
实例属性组成的字典:{'_name': 'zhangsan', '_age': 18}
__bases__
属性和__mro__
表的代码如下:
class Parent1:
pass
class Parent2:
pass
class Parent3(Parent1):
pass
class Parent4(Parent2):
pass
class Sub(Parent3, Parent4):
pass
print(f"Sub类的直接父类有:{Sub.__bases__}")
print(f"__mro__表为:{Sub.__mro__}")
输出:
Sub类的直接父类有:(<class '__main__.Parent3'>, <class '__main__.Parent4'>)
__mro__表为:(<class '__main__.Sub'>, <class '__main__.Parent3'>, <class '__main__.Parent1'>,
<class '__main__.Parent4'>, <class '__main__.Parent2'>, <class 'object'>)
参考文章:python 继承(史上最详细版本)
2. 抽象类
(1)包含抽象方法的类被称为抽象类。抽象类的特征: 抽象类不能实例化对象;在抽象类中,可以存在抽象方法,也可以存在普通方法;在抽象类中可以添加成员属性;子类必须实现(重写)抽象类中所有的抽象方法。
(2)在Python中,抽象类或抽象基类(Abstract Base Classes,简称ABC)是一个包含抽象方法(即只有方法签名而没有具体实现)的类,它的主要作用是定义一组接口或规范,而不是提供具体的实现。在Python中,可以使用abc模块
来定义抽象基类,其中@abc.abstractmethod
作用是把对象方法变成抽象对象方法;@abc.abstractclassmethod
(已弃用)作用是把类方法变成抽象类方法;@abc.abstractstaticmethod
(已弃用)作用是把静态方法变成抽象的静态方法。但是@abc.abstractmethod
修饰符可与其他修饰符(@classmethod,@staticmethod,@property
等)一起使用,分别来构成抽象的类方法,抽象的静态方法,抽象属性等。定义抽象基类的方式有两种:
- 方式一:
from abc import ABCMeta, abstractmethod
# 抽象类
class Person(metaclass=ABCMeta):
# 抽象方法
@abstractmethod
def run(self):
pass
# 抽象方法
@abstractmethod
def show(self):
pass
"""
abc模块的ABCMeta类继承自type,可以作为其他类的元类,来实现抽象基类的效果。
ABCMeta类的作用之一便是检查是否所有的抽象方法或特性均被重写,如果没有,则实例无法被创建。
ABCMeta类不会出现在Python抽象基类和其派生类的方法解析顺序(Method Resolution Order,MRO)中,
ABCMeta类不是Python抽象基类的父类。
"""
- 方式二:
from abc import ABC, abstractmethod
# 抽象类
class Person(ABC):
# 抽象方法
@abstractmethod
def run(self):
pass
# 抽象方法
@abstractmethod
def show(self):
pass
# 在这个例子中,定义了一个名为Person的抽象基类,该抽象类包含两个抽象方法:run()和show()方法。
"""
abc模块的ABC类是一个辅助类(Helper Class),他将ABCMeta指定为元类, 从ABC派生的Python
类会成为抽象基类。与ABCMeta类不同,ABC会出现在Python抽象基类和其派生类的方法解析顺序中(__mro__表中),
ABC类是Python抽象基类的父类。
"""
(3)子类继承普通父类的代码示例:
class Parent:
def __init__(self, name: str,age: int) -> None:
self.name = name
self.age = age
# 已经实现的普通方法
def show(self):
print(f"name = {self.name},age = {self.age}")
# 没有实现的普通方法
def hobby(self):
pass
class Sub(Parent):
# 重写父类的方法
def show(self):
print(f"子类name = {self.name},子类age = {self.age}")
sub = Sub("zhangsan",20)
sub.show()
sub.hobby()
输出:
子类name = zhangsan,子类age = 20
(4)子类继承抽象父类(抽象基类)的示例:
from abc import ABC, abstractmethod
# 抽象类
class Parent(ABC):
def __init__(self, name: str,age: int) -> None:
self.name = name
self.age = age
# 已经实现的普通方法
def show(self):
print(f"name = {self.name},age = {self.age}")
# 抽象方法
@abstractmethod
def hobby(self):
pass
class Sub(Parent):
# 必须重写父类的hobby方法,否则会报错
def hobby(self):
print("喜欢钓鱼")
sub = Sub("zhangsan",20)
sub.show()
sub.hobby()
输出:
name = zhangsan,age = 20
喜欢钓鱼
参考文章:
Python中的抽象类(简单易懂版)
Python 抽象基类(Abstract Base Classes)
Python 抽象类,抽象方法介绍,以及定义和实现 Python 抽象类,抽象方法