0%

Python之类的继承、抽象类

这里介绍Python如何实现类的继承 与 使用抽象类

abstract.png

类的继承

Python中类的继承很简单,只需在定义类时,通过括号指定需要继承的父类即可。同时由于Python支持多继承特性,故可以在括号中指定多个父类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
title = "类的继承"
print(f"------------ {title} -------------------")

# 类:继承
class Car:
"""
汽车
"""

def __init__(self, brand, type, price):
self.brand = brand
self.type = type
self.price = price

def info(self):
print("Brand:", self.brand, "Type:", self.type, "Price:", self.price)

def drive(self):
print("The Car is running ...")

# BMW 继承 Car类
class BMW(Car):
"""
宝马汽车
"""

def __init__(self, type, price, support_electric):
# 通过super()函数调用父类的构造方法
super().__init__("宝马", type, price)
self.support_electric = support_electric

def can_use_electric(self):
if self.support_electric :
print("本车支持电动")
else:
print("本车不支持电动")

# 重写父类方法
def drive(self):
print("宝马在狂飙中...")


my_bmw = BMW("SUV", 1111, True)

print("\n调用父类方法")
my_bmw.info()

print("\n调用子类方法")
my_bmw.can_use_electric()
my_bmw.drive()

print("\n访问父类的属性")
print("My BMW Price is", my_bmw.price)

print("\n访问子类的属性")
print("My BMW support electric:", my_bmw.support_electric)


print("\n子类判断")
print("BMW 是否为 Car 的子类", issubclass(BMW, Car) )
print("BMW 是否为 BMW 的子类", issubclass(BMW, BMW) )

print("\n类型判断")
print("变量 my_bmw 是否为 Car 类型 ", isinstance(my_bmw, Car) )
print("变量 my_bmw 是否为 BMW 类型 ", isinstance(my_bmw, BMW) )

print("\n通过特殊属性 __bases__ 获取其基类信息")
print("Car类的基类:", Car.__bases__)
print("BMW类的基类:", BMW.__bases__)

figure 1.png

抽象类

定义抽象类很简单。只需继承abc模块中的ABC类即可。 然后在抽象方法上 @abstractmethod装饰器 来标记该方法为抽象方法,子类需要实现。此外,抽象类可以包含具体方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from abc import ABC, abstractmethod

# 定义抽象类,首先需要继承 abc模块中的ABC类
class Animal(ABC):
def __init__(self, type, name) :
self.type = type
self.name =name

# 抽象类可以包含 具体方法
def hello(self):
print("Hello, My Name is", self.name)

# 添加 @abstractmethod装饰器 标记该方法为抽象方法,子类需要实现
@abstractmethod
def get_type_info(self):
pass

需要注意的是,当其他装饰器与@abstractmethod装饰器一起使用时。需保证@abstractmethod装饰器在最里层,示例如下。即 @abstractmethod装饰器 与 def语句 之间不能有其他装饰器

1
2
3
4
5
6
class Man(ABC):

@classmethod
@abstractmethod
def help_4_debug(cls):
pass

现在我们来实现Animal这个抽象类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Cat(Animal):
def __init__(self, type, name):
# 通过super()函数调用父类的构造方法
super().__init__(type, name)

def get_type_info(self):
print("My Type is", self.type)


try:
my_animal = Animal("Dog", "Bob")
except Exception as e:
print("不能实例化抽象类,",e)

my_cat = Cat("英短猫", "Tom")
my_cat.hello()
my_cat.get_type_info()

figure 2.png

拷贝

Python中有浅拷贝、深拷贝之分。所以我们在拷贝实例时需要特别注意,以免使用浅拷贝时发生意外情况。这里简单以嵌套列表来进行说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import copy

list1 = [0,1,2,["Aaron","Tom"],4,5]
# copy: 浅拷贝
list2 = copy.copy(list1)
# deepcopy: 深拷贝
list3 = copy.deepcopy(list1)

print("----------------- 修改前 ----------------------------")
print(f"list 1, id:{id(list1)} -->> {list1}")
print(f"list 2, id:{id(list2)} -->> {list2}")
print(f"list 3, id:{id(list3)} -->> {list3}")

list1[1] = 111
list1[3].append("Davlid")

print("----------------- 修改后 ----------------------------")
print(f"list 1, id:{id(list1)} -->> {list1}")
print(f"list 2, id:{id(list2)} -->> {list2}")
print(f"list 3, id:{id(list3)} -->> {list3}")

figure 3.png

参考文献

  1. Python编程·第3版:从入门到实践 Eric Matthes著
  2. Python基础教程·第3版 Magnus Lie Hetland著
  3. 流畅的Python·第1版 Luciano Ramalho著
请我喝杯咖啡捏~

欢迎关注我的微信公众号:青灯抽丝