前言:第五节课主要加深扩展类的相关知识,重点在继承。虽然多次入门python,但是对继承几乎没用过,所以这次学到很多新只是。也明白到,在Python中,开发时,继承是一个很重要的功能——常常在别人的代码上改东西,而不是从头自己写。
目录
———————————————
【AI Studio】《零基础Python速成营》 课程笔记 —— 05
依据:课程链接或个人博客
https://blog.csdn.net/Lovely_him?spm=1010.2135.3001.5343
一、类的继承
菜鸟教程 - Python 子类继承父类构造函数说明
https://www.runoob.com/w3cnote/python-extends-init.html
- 目前从代码上看,可以得出类的继承,就相当于把父类的东西全都复制粘贴到子类里去了。
- 然后,如果子类有和父类命名冲突的就会重写覆盖。
# 父类
class Athlete:
def __init__(self,a_name,a_dob=None,a_times=[]):
self.name = a_name
self.dob = a_dob
self.times = a_times
def top3(self):
return sorted(set([self.sanitize(t) for t in self.times]))[0:3]
def sanitize(self,time_string):
if '-' in time_string:
splitter = '-'
elif ':' in time_string:
splitter = ':'
else:
return (time_string)
(mins,secs) = time_string.split(splitter)
return (mins+'.'+secs)
# 子类
class Rugby(Athlete):
def __init__(self,a_name,a_bod,a_squat,a_times):
#调用父类__init__
Athlete.__init__(self,a_name,a_bod,a_times)
#深蹲次数
self.squat = a_squat
# 继承后下面两个函数就在Rugby类中,只是看不到而已
# def top3(self):
# return sorted(set([self.sanitize(t) for t in self.times]))[0:3]
# def sanitize(self,time_string):
# if '-' in time_string:
# splitter = '-'
# elif ':' in time_string:
# splitter = ':'
# else:
# return (time_string)
# (mins,secs) = time_string.split(splitter)
# return (mins+'.'+secs)
1)子类 的 构造函数
定义:
class 子类名(父类名):
情况1,如果子类有新增的属性,那么需要在子类__init方法中,调用父类的__init__
情况2,如果子类没有新增的属性,子类不需要写__init__方法
使用:
对象名 = 子类名(参数)
继承的好处:代码重用,升级功能(重写),新增功能(新的方法)
- 菜鸟教程下的一篇笔记总结的很好,
情况一:子类需要自动调用父类的方法:子类不重写__init__()方法,实例化子类后,会自动调用父类的__init__()的方法。
(即,子类不需要再往构造函数里加东西,所以不用重写)
情况二:子类不需要自动调用父类的方法:子类重写__init__()方法,实例化子类后,将不会自动调用父类的__init__()的方法。
(即,子类需要加东西,要重写,正常情况即使重写也要保留父类的,所以大多会是第三种情况)
情况三:子类重写__init__()方法又需要调用父类的方法:使用super关键词:
super(子类,self).__init__(参数1,参数2,....)
class Son(Father):
def __init__(self, name):
super(Son, self).__init__(name)
(不用super也可以,老师上课讲了种较好理解的,这样也可以)
class Son(Athlete):
def __init__(self,name,name2):
Father.__init__(self,name)
2)子类 的 方法重写
子类方法与父类方法完全相同,子类若重写了父类的方法,则子类对象调用方法时就是调用的自己类中重新的方法。
- 其实子类构造函数应该也算一种重写(只是重写完后还能调用父类的执行?)。
- 值得注意的是!!!!不止是方法的名字要一样,连参数也要一致。不然仍会被认定为2个不同的方法。大概父类构造函数就是因为这样才没有被重写覆盖。
3)专业名词:多态性
多态性:一个事物多种形态
多态的好处是:减少重复代码,分离经常改变的代码与不经常改变的代码,使得代码可维护性提高。
- 从代码上看,多态性其实就相当于把类作为参数传入函数内,在函数内被调用。(应该也算高阶函数的一种)
- 当2个类方法名一样,功能不一样时,就可以使用多态性来减少重复性,使代码更加整洁。
loren = get_coach_data('mywork/loren.txt')
mark = get_coach_data('mywork/mark.txt')
loren = Rugby(loren.pop(0),loren.pop(0),loren.pop(0),loren)
mark = OtherAthlete(mark.pop(0),mark.pop(0),mark.pop(0),mark)
def print_rugby(athlete):
print(athlete.name)
print(athlete.dob)
print(athlete.squat)
print(athlete.top3())
print_rugby(loren)
print_rugby(mark)
4)多继承
- 用起来和单继承区别不大,唯一需要注意的就是:多个父类有相同的属性或方法名,这种情况应该避免。
菜鸟教程 - Python super() 函数
https://www.runoob.com/python/python-func-super.html
#多个父类有相同的属性或方法名,这种情况应该避免
class Father():
def __init__(self):
self.color = 'black'
def talk(self):
print("---爸爸的表达能力---")
class Mather():
def __init__(self):
self.color = 'white' # 重复命名了。
def talk(self):
print("--妈妈也能表达")
def smart(self):
print("---妈妈聪明的头脑---")
class Child(Father,Mather):
pass
child1 = Child()
child1.talk()
child1.smart()
print(child1.color)
# 这里会输出Father类的color。应该涉及到继承优先级的问题。
二、提问
1)问题①
导入athlete模块,使用athlete模块下的所有代码
- 其实就是教:“
函数→类→模块→包
”的封装思路。
import sys
sys.path.append('mywork')
# import athlete
# print(dir(athlete))
from athlete import *
loren = get_coach_data('mywork/loren.txt')
mark = get_coach_data('mywork/mark.txt')
loren = Rugby(loren.pop(0),loren.pop(0),loren.pop(0),loren)
mark = OtherAthlete(mark.pop(0),mark.pop(0),mark.pop(0),mark)
def print_rugby(athlete):
print(athlete.name)
print(athlete.dob)
print(athlete.squat)
print(athlete.top3())
print_rugby(loren)
print_rugby(mark)fj飞桨
2)问题②
如果有一个模块mymodule.py中也包含get_coach_data函数,该怎么区分这两个函数呢
import sys
sys.path.append('work')
from p1.mymodule import *
from p2.mymodule import *
import p1
import p2
p1.mymodule.demo()
p2.mymodule.demo()
# 输出:
# p1 -- mymodule
# p1 -- mymodule