本篇文章主要是对python学习时的一些总结,作为学习笔记记录。
上篇文章主要介绍类中的方法。本篇文章主要是对python中的继承进行简单介绍。
C/C++是一种面向对象的编程语言,C/C++在表示继承时,用特定的形式表示这种继承关系,而在python中,继承关系也具有特定的定义格式。
class DerivedClass(BaseClassName):
pass
BaseClassName表示父类或者是基类,这种继承关系只有在当前作用域中能够访问到BaseClassName时才成立,否则会提示报错。BaseClassName也可以是第三方工具包中的基类,只要通过import正常导入就可以合理继承。
在继承关系中,构造方法会涉及到基类和派生类的初始化,是相对比较重要的一个方法。
对于含有构造方法的普通类来说,其形式可能是这样的:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
aa = A(1,2)
print(aa.a, aa.b)
而在继承关系中,如果子类中需要父类的构造方法就需要显示的调用父类的构造方法,或者不重写父类的构造方法。也就是说,字类不重写__init__实例化子类时,会自动调用父类定义的__init__()。
class A:
def __init__(self, a, b):
print("This is A's __init__.")
self.a = a;
self.b = b;
def display(self):
print(self.a, self.b)
class B(A):
pass
bb = B(1, 2)
bb.display()
结果为:
This is A's __init__.
1 2
从上面的结果也可以看出,如果子类不重写__init__()进行子类实例化时,会自动调用父类定义的__init__()。
而如果子类重写了__init__时进行子类实例化时,就不会调用父类定义的__init__(),而会调用子类自身的__init__():
class A:
def __init__(self, a, b):
print("This is A's __init__.")
self.a = a;
self.b = b;
def display(self):
print(self.a, self.b)
class B(A):
def __init__(self, a, b):
print("This is B's __init__")
self.a = b
self.b = a
def display(self):
print(self.a, self.b)
bb = B(1, 2)
bb.display()
结果为:
This is B's __init__
2 1
也就是说,子类重写__init__()实例化子类时,会调用子类自身的__init__()。
但如果重写了__init__(),同时要继承父类的构造方法时,可以使用super关键字或者经典写法:
上面的两种形式都可以实现基类构造方法的调用:
class A:
def __init__(self, a, b):
print("This is A's __init__.")
self.a = a;
self.b = b;
def display(self):
print(self.a, self.b)
class B(A):
def __init__(self, a, b, c):
print("This is B's __init__")
super(B, self).__init__(a, b)
self.c = c
def display(self):
print(self.a, self.b, self.c)
class C(A):
def __init__(self, a, b, c):
print("This is C's __init__")
A.__init__(self, a, b)
self.c = c
def display(self):
print(self.a, self.b, self.c)
bb = B(1, 2, 3)
bb.display()
cc = C(4, 5, 6)
cc.display()
结果为:
This is B's __init__
This is A's __init__.
1 2 3
This is C's __init__
This is A's __init__.
4 5 6
从上面的结果也可以看出,两种调用基类构造方法的结果是相同的。也就是说:
- 子类不重写父类的__init__(),会自动调用父类的__init__()
- 子类重写父类的__init__(),会调用自身的__init__()
- 子类重写__init__()又要调用父类的__init__()需要借助super关键字或者经典写法
在继承关系中,有时父类和子类对于同一属性的操行可能不同,但是为了避免过多地定义方法名,可能会选择进行同名方法重写。
class A:
def func(self):
print("A")
class B(A):
def func(self):
print("B")
bb = B()
bb.func()
结果为:
而如果要调用父类的同名函数,则需要使用super()函数。
super()函数可以用来调用父类方法。语法为:
super(type[, object-or-type])
type是类名,object-or-type一般是self。
class A:
def func(self):
print("A")
class B(A):
def func(self):
print("B")
bb = B()
bb.func()
super(B, bb).func()
结果为:
B
A
在类内部使用super()函数可以省略掉该函数的参数:
class A:
def func(self):
print("A")
class B(A):
def func(self):
print("B")
super().func()
bb = B()
bb.func()
利用super()函数可以解决多重继承中可能遇到的问题,例如查找顺序(MRO,类的方法解析顺序表),重复调用问题等。
方法重写一般会涉及到面向对象中的多态,在C/C++中的接口设计中,我们会将接口形参设定为基类的指针或引用,而在实际的调用中可以利用此接口传入基类或者派生类的对象。在python中也可以实现多态:
class A:
def func(self):
print("A")
class B(A):
def func(self):
print("B")
class C(A):
def func(self):
print("C")
def foo(x):
x.func()
aa = A()
bb = B()
cc = C()
foo(aa)
foo(bb)
foo(cc)
结果为:
A
B
C
这种在一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现的行为就叫做多态。但是在python中,由于python这门编程语言本身的特性,我们有时很难从函数的参数列表分辨出是否存在多态这种特性。
在之前的继承关系中,都只是说明了单继承,但是在使用时,可能涉及到多继承,多继承是指一个子类在继承时存在多个父类。
class DerivedClassName(BaseClassName1, BaseClassName2...):
pass
继承中基类的先后顺序说明了子类进行同名方法调用时的搜索顺序:
class A:
def __init__(self):
print("This is A's __init__.")
def display(self):
print("A's display")
def func(self):
print("A's func")
class B:
def __init__(self):
print("This is B's __init__.")
def display(self):
print("B's display")
def func(self):
print("B's func")
class C(A, B):
def __init__(self):
print("This is C's __init__.")
def display(self):
print("C's display")
cc = C()
cc.display()
cc.func()
结果为:
This is C's __init__.
C's display
A's func
从上面的结果可以看出,如果子类中存在同名方法会调用自身的方法,如果子类中不存在该方法,会按照继承关系中父类出现的先后顺序进行搜索并调用。
Original: https://blog.csdn.net/SAKURASANN/article/details/111398006
Author: 止步听风
Title: Python基础编程(二十二)——类与对象3
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/783520/
转载文章受原作者版权保护。转载请注明原作者出处!