【写在前面】今天更新python自学系列第二讲---类的继承与定制。第一讲在这里:https://blog.youkuaiyun.com/include_645829461/article/details/90347233
希望看见文章的大佬们可以指点自己的不足,因为本人也学过部分java和c++,所以在更新这块部分的内容的时候会把它与java或者c++做类比。之前学的语法会在后面一一更新,敬请期待。(声明:这里用到的图片,都是风变编程提供,在此鸣谢,也希望大家如果有机会可以考虑去风变编程学一下python)
类的继承
什么是类的继承?顾名思义,继承继承,那就是子类拥有父类的一切东西,包括类的属性和方法。(这里没有讲私有的属性和方法,不知道python是否也有私有的和公有之分,感兴趣的老铁可以自行百度)
那么我是我父亲的孩子,我就会拥有我父亲的特征,譬如说黄皮肤、黑眼睛、黑头发。那么现实生活中我就会有我父亲的一些行为特征,譬如说我吃饭也用筷子等等。这就是我继承了我父亲。编程语言中这个叫继承。在Python中,我们的习惯表述是:A类是B类的子类,而B类是A类的父类(或超类)。
【基本语法】
如果说子类A继承了父类B,那么你要在小括号里写上父类的名字B,就一个B就行,不用写 class B。就像下图所示:
之后你就可以用子类的实例(对象)来调用父类的方法和属性了,譬如说像这样:
class Chinese:
eye = 'black'
def eat(self):
print('吃饭,选择用筷子。')
class Cantonese(Chinese):
# 通过继承,Chinese类有的,Cantonese类也有
pass
# 验证子类可以继承父类的属性和方法,进而传递给子类创建的实例
yewen = Cantonese()
# 子类创建的实例,从子类那间接得到了父类的所有属性和方法
print(yewen.eye)
# 子类创建的实例,可调用父类的属性
yewen.eat()
# 子类创建的实例,可调用父类的方法
这个的输出结果是:
black
吃饭,选择用筷子。
为什么会输出这个呢?还记得我们说类的继承吗?这里Cantonese类继承了父类Chinese,所以你别看这个子类下面就一个pass,但是其实他把父类的属性和方法都复制粘贴过去了,所以他可以调用父类的属性和方法。
下面讲一下继承的宽度和深度:
宽度:你可以理解成一个孩子可以有多个爸爸(好像有点违法),但是这在python中是合法的。java是单根继承(一个孩子就只有一个爸爸),python的宽度就像c++的继承一样,可以多重继承。
语法为class A(B,C,D):
这里classA继承了类B、C、D。但是这里的多重继承又有个癖好,那就是他会先去找离自己近的父亲。这可谓是近水楼台先得月。他要是在B类中找不到那就去C类找。而此时如果B类又继承了一个类叫E类,那么找不到的话会优先去B类的父亲E类中找。
举个不恰当的例子,小明有三个爸爸:B、C、D,B也有一个爸爸叫E。小明有天想要psp,他就先去离自己住的近的父亲B家中找,没有,那就去自己的爷爷E家中找PSP,找到了之后就不跑腿去别的爸爸中找了。这就是多重继承与多层继承。
深度:你可以类比为我有爸爸、我也可以有爷爷、有祖爷爷等等。这样的话我就可以有祖爷爷的属性和方法。这就是多层继承。
可以来个图来继续了解一下:
这里举个小栗子:
如果要写上图的关系,并且打印出来C4的那么num,那么结果是什么呢?我们可以先分析一下:
C4有三个爸爸:C1、C2、C3,他还有个C2对应的爷爷,那么他会先去找谁的num呢?根据就近原则,会先去找C1的,C1的num是1,那C4就不去拜托别的爸爸了,就直接输出1.那C4的name又是什么呢?他又去找,C1没有name,他就去C2找,C2也没有,那就去找爷爷,爷爷有name,那就直接打印name 是C0.让我们看一下具体实现代码:
class C0:
name = 'C0'
class C2(C0):
num = 2
class C1:
num = 1
class C3:
name = 'C3'
class C4(C1,C2,C3):
pass
ins = C4()
print(ins.name) # 打印出C0
print(ins.num) # 打印出1
这个的结果是:
C0
1
那既然通过继承,子类有父类的属性和方法,那既然我都有父类了,那我还要一模一样的子类干啥。就像你和你父亲不一定一模一样吧,你会有自己的性格特征,会有自己的穿衣打扮风格,会有自己的性别。那些子类的个性化的信息怎么搞呢?接下来就讲类的定制。
类的定制:
直接看代码来理解一下:
class Chinese:
eye = 'black'
def eat(self):
print('吃饭,选择用筷子。')
class Cantonese(Chinese): # 类的继承
native_place = 'guangdong' # 类的定制
def dialect(self): # 类的定制
print('我们会讲广东话。')
yewen = Cantonese()
print(yewen.eye)
# 父类的属性能用
print(yewen.native_place)
# 子类的定制属性也能用
yewen.eat()
# 父类的方法能用
yewen.dialect()
# 子类的定制方法也能用
输出结果:
black
guangdong
吃饭,选择用筷子。
我们会讲广东话。
1.我们可以在子类下新建属性或方法,让子类可以用上父类所没有的属性或方法。
2.我们也可以重写父类的方法或属性。重写代码,是在子类中,对父类代码的修改。
给个代码理解一下:
class Chinese:
def land_area(self,area):
print('我们居住的地方,陆地面积是%d万平方公里左右。'% area)
class Cantonese(Chinese):
# 直接对方法进行重写
def land_area(self,area):
print('我们居住的地方,陆地面积是%d万平方公里左右。'% int(area*0.0188))
gonger = Chinese()
yewen = Cantonese()
gonger.land_area(960)
yewen.land_area(960)
运行结果:
这里就是重写,子类重写了父类的方法,那么如果子类去执行方法的时候就会选择执行自己新写的方法。这很好理解,如果他继续去执行父类的方法,那么你重写的那几行代码不是废了?编辑器没那么傻,他一看你子类有这个方法,他就直接就近执行你的方法了,他才不会那么傻的去父类,他也会累的。
不过你还可以用下面这种方法来重写:
class Chinese:
def land_area(self,area):
print('我们居住的地方,陆地面积是%d万平方公里左右。'% area)
class Cantonese(Chinese):
# 间接对方法进行重写
def land_area(self, area, rate = 0.0188):
Chinese.land_area(self, area * rate)
# 直接继承父类方法,再调整参数。
gonger = Chinese()
yewen = Cantonese()
gonger.land_area(960)
yewen.land_area(960)
子类继承父类方法的操作是在def
语句后接父类.方法(参数)
,如上述代码的第八、九行。这样一来,父类方法land_area
中的说法改变,子类也不用去动,因为子类直接继承了父类的方法。只不过,在继承的基础上,通过参数的调整完成了定制。参数的调整,可以增加参数(如 rate),也可以改变参数的默认值,如下:
class Chinese:
def land_area(self,area):
print('我们居住的地方,陆地面积是%d万平方公里左右。' % area)
class Cantonese(Chinese):
# 为参数 area 设置默认值。
def land_area(self, area = 960, rate = 0.0188):
Chinese.land_area(self, area * rate)
yewen = Cantonese()
yewen.land_area()
# 两个参数都有默认值,所以可以这么调用。
【写在后面】今天的总结就到这里,有什么不清楚的地方欢迎下方留言评论,再次感谢风变编程。博主还是个学生,可能不太有时间会每天更新博客,但是有时间我就会更的(立个flag)!