python面向对象的继承

python学习笔记之继承

继承

先来看一个例子,以门这个类为例子,如下:

1
2
3
4
5
6
7
8
9
10
class Door:
def __init__(self,number,status):
self.number = number
self.status = status

def open(self):
self.status = 'opening'

def close(self):
self.status = 'closed'

上边这个“Door”类实现了两个方法,一是open,表示把门打开,另一是close,表示把门关闭。如果想对门加把锁,门是锁着的就打不开门,锁是打开状态时才能打开门,这时我们可以重新实现这个类,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class LockableDoor:
def __init__(self,number,status,is_lock):
self.number = number
self.status = status
self.is_lock = is_lock

def open(self):
if not self.is_lock:
self.status = 'opening'
else:
print('is locked')

def close(self):
self.status = 'closed'

def lock(self):
if self.status == 'closed':
self.is_lock = 'True'
else:
print('is opening')

上边的LockableDoor类实现了我们所需要的功能,它是完全舍弃了Door类而重新实现的类,有没有方法在不舍弃Door类的情况下实现我们所需要的功能呢?类的继承特性就可以实现,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class LockableDoor_1(Door):
def __init__(self,number,status,is_lock):
super(LockableDoor_1,self).__init__(number,status)
self.is_lock = is_lock

def open(self):
if not self.is_lock:
super(LockableDoor_1,self).open()
else:
print('is locked')

def lock(self):
if self.status == 'closed':
self.is_lock = True
else:
print('is opening')

在分析上边代码前先来理清几点:

没有加锁的门(Door类)有以下方法:

  1. 打开门(open),直接把状态(status)设置为成打开状态(opening)

  2. 关闭门(close),直接把状态(status)设置成关闭状态(closed)

一个有锁的门(LockableDoor_1)有以下方法:

  1. 打开门(open),先要看下门是否被锁住了,如果没有锁住才能把状态(status)设置成打开状态(oipening),否则就提示门是被锁住的,无法打开等信息,而一个没有上锁的门和一个没有锁的门对打开门这个动作都是相同的,所在这里可以用超类的的open方法

  2. 关闭门(close),一个没锁的门要想关闭门把状态(status)设置成关闭状态(closed),那对一个有锁的门呢?也是一样,不管门是否上锁,我们只需把门状态(status)设置成关闭状态(closed),所以对关闭门来说与Door类中的close方法并没有差异

  3. 上锁(lock),一个有锁的门会有加不加锁这个动作

通过上边的分析可知:

在不完全舍弃Door类的情况下实现一个有锁的门这个类,那需要在Door类的基础上重新实现一个open方法,即重写open方法,并增加一个lock方法,而close方法完全可以利用Door类中的。

现在来分析一下LockableDoor_1这个类中的代码:

  1. 第一行class LockableDoor_1(Door):表示LockableDoor_1类继承Door类,DoorLockableDoor_1的超类,也叫父类或基类

  2. 第二至四行是重写了构造方法,因为增加了is_lock实例属性,其中super(LockableDoor_1,self).__init__(number,status)是表示用supper函数调用了超类的__init__方法,即在LockableDoor_1类中实例化了超类(Door)

  3. 第六到十行是重写了open方法,其中super(LockableDoor_1,self).open()表示调用父类的open方法

  4. 针对超类的close方法不用重写,直接继承即可

继承与可见性

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
70
71
72
73
class A:
public_class_var = 'public class var'
__private_class_var = 'private class var'

def __init__(self):
self.public_instance_var = 'public instance var'
self.__private_instance_var = 'private instance var'

def public_instance_method(self):
try:
print(self.public_class_var)
except:
pass

try:
print(self.__private_class_var)
except:
pass

try:
print(self.public_instance_var)
except:
pass

try:
print(self.__private_instance_var)
except:
pass

def __private_instance_method(self):
try:
print(self.public_class_var)
except:
pass

try:
print(self.__private_class_var)
except:
pass

try:
print(self.public_instance_var)
except:
pass

try:
print(self.__private_instance_var)
except:
pass

@classmethod
def public_class_method(self):
try:
print(self.public_class_var)
except:
pass

try:
print(self.__private_class_var)
except:
pass

@classmethod
def __private_class_method(self):
try:
print(self.public_class_var)
except:
pass

try:
print(self.__private_class_var)
except:
pass
1
2
class B(A):
pass
1
b = B()
1
dir(b)
['_A__private_class_method',
 '_A__private_class_var',
 '_A__private_instance_method',
 '_A__private_instance_var',
 '__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'public_class_method',
 'public_class_var',
 'public_instance_method',
 'public_instance_var']

dir(b)输出的列表的最后四个元素可总结如下规则:

  1. 子类可继承超类的公有方法,包括公有类方法和公有实例方法;子类可继承超类的公有变量,包括公有类变量和公有实例变量

可概括如下:

  • 公有方法和变量(类和实例)是可继承的

  • 私有方法和变量(类和实例)是不可继承的

来调用验证一下:

1
b.public_class_method() #公有类方法可访问公有和私有的类变量
public class var
private class var
1
b.public_class_var
'public class var'
1
b.public_instance_method() #公有的实例方法可访问公有和私有类变量,也能访问公有和私有实例变量
public class var
private class var
public instance var
private instance var
1
b.public_instance_var
'public instance var'

如果在子类中把类变量和实例变量重写后,那子类访问到的变量是自己的,还是父类的呢?做如下验证:

1
2
3
4
5
6
7
8
class C(A):
public_class_var = 'child public class var'
__private_class_var = 'child private class var'

def __init__(self):
super(C,self).__init__()
self.public_instance_var = 'child public instance var'
self.__private_instance_var = 'child private instance var'
1
c = C()
1
c.public_instance_method()
child public class var
private class var
child public instance var
private instance var
1
c.public_class_method()
child public class var
private class var
1
c.public_class_var
'child public class var'
1
c.public_instance_var
'child public instance var'

经过上边的验证可得到如下结论:

  1. 父类的公有方法(类和实例)访问父类的私有变量,即使在子类中私有变量被重写了

  2. 子类中对公有变量重写后,父类的公有方法(类和实例)访问的是子类的公有变量

文章目录
  1. 1. 继承
    1. 1.1. 继承与可见性
|