python中的继承关系和抽象类

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 抽象类,抽象方法

  • 14
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值