Python 入门学习笔记(六)

一、类的继承(子类、父类)
Python是一门面向对象的编程语言,支持类继承。新的类称为子类Subclass,被继承的类称为父类、基类或者超类。子类继承父类后,就拥有父类的所有特性。

五个内容模块
0):定义子类
1):继承父类初始化过程中的参数
2):调用父类的__init__方法,定义新增子类属性
3):直接调用父类属性方法
4):重写父类属性方法
5):强制调用父类私有属性方法

(0)定义子类、
(1)继承父类初始化过程中的参数、
(2)调用父类的__init__方法,定义新增子类属性
定义子类的方法

定义: class 子类名(父类名):
情况1:如果子类有新增的属性,那么需要在子类__init__方法中,调用父类的__init__ 指的是需要在子类属性__init__中调用,father.__init__,再自定义新增的子类。也可以用super().__init__()方法继承父类的属性
情况2:如果子类没有新增的属性,子类不需要写__init__方法 使用: 对象名 = 子类名(参数)

#读取数据
def get_coach_data(filename):
    with open(filename) as f:
        line = f.readline()
    return line.strip().split(',')
#定义父类
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)

(3)调用父类属性方法

loren = get_coach_data('mywork/loren.txt')
rugby = Rugby(loren.pop(0),loren.pop(0),loren.pop(0),loren)
print('姓名:%s,生日:%s,深蹲:%s个,最块的3次成绩:%s' %(rugby.name,rugby.dob,rugby.squat,rugby.top3()))
#OUTPUT
姓名:2011-11-3,生日:270,深蹲:3.59个,最块的3次成绩:['3.11', '3.23', '4.10']

(4)重写父类属性方法

子类方法与父类方法完全相同,子类若重写了父类的方法,则子类对象调用方法时就是调用的自己类中重新的方法。
具体方法:直接定义一个方法函数名称与父类方法函数一致,重写方法函数中具体的内容即可。

class OtherAthlete(Athlete):
    def __init__(self,a_name,a_bod,a_squat,a_times):

        Athlete.__init__(self,a_name,a_bod,a_times)

        self.squat = a_squat
    def top3(self):
        return sorted([self.sanitize(t) for t in self.times])[0:3]
mark = get_coach_data('mywork/mark.txt')
mark = OtherAthlete(mark.pop(0),mark.pop(0),mark.pop(0),mark)
print('姓名:%s,生日:%s,深蹲:%s个,最快的3次成绩:%s' %(mark.name,mark.dob,mark.squat,mark.top3()))
#OUTPUT
姓名:mark,生日:2010-2-4,深蹲:300个,最快的3次成绩:['3.11', '3.11', '3.23']

(5)强制调用父类私有方法

如果父类的方法是私有方法,如 def __action(self) 这样的话再去调用就提示没有这个方法,其实编译器是把这个方法的名字改成了 _Father__action(),如果强制调用,可以这样

class Father():
    def __action(self):  # 父类的私有方法
        print('调用父类的方法')
 
class Son(Father):
    def action(self):
        super()._Father__action()
son=Son()
son.action()
#OUTPUT
调用父类的方法

二、多态性

多态的作用:让具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容(功能)的函数。
多态的特点:
1、只关心对象的实例方法是否同名,不关心对象所属的类型;
2、对象所属的类之间,继承关系可有可无;
3、多态的好处可以增加代码的外部调用灵活度,让代码更加通用,兼容性比较强;
4、多态是调用方法的技巧,不会影响到类的内部设计。

(1)对象所属的类之间没有继承关系时

调用同一个函数fly(), 传入不同的参数(对象),可以达成不同的功能

class Duck(object):                                  # 鸭子类
    def fly(self):
        print("鸭子沿着地面飞起来了")

class Swan(object):                                  # 天鹅类
    def fly(self):
        print("天鹅在空中翱翔")

class Plane(object):                                 # 飞机类
    def fly(self):
        print("飞机隆隆地起飞了")

def fly(obj):                                        # 实现飞的功能函数
    obj.fly()

duck = Duck()
fly(duck)

swan = Swan()
fly(swan)

plane = Plane()
fly(plane)
#OUTPUT
鸭子沿着地面飞起来了
天鹅在空中翱翔
飞机隆隆地起飞了

(2)对象所属的类之间有继承关系(应用更广)

class gradapa(object):
    def __init__(self,money):
        self.money = money
    def p(self):
        print("this is gradapa")
 
class father(gradapa):
    def __init__(self,money,job):
        #用super()方法继承父类的属性
        super().__init__(money)
        self.job = job
    def p(self):
        print("this is father,我重写了父类的方法")
 
class mother(gradapa): 
    def __init__(self, money, job):
        super().__init__(money)
        self.job = job
 
    def p(self):
         print("this is mother,我重写了父类的方法")
         return 100
         
#定义一个函数,函数调用类中的p()方法
def fc(obj): 
    obj.p()
gradapa1 = gradapa(3000) 
father1 = father(2000,"工人")
mother1 = mother(1000,"老师")

fc(gradapa1)            #这里的多态性体现是向同一个函数,传递不同参数后,可以实现不同功能.
fc(father1)
print(fc(mother1))
#OUTPUT
this is gradapa
this is father,我重写了父类的方法
this is mother,我重写了父类的方法
100

三、多继承

一个子类可以继承多个父类是多继承
一层层继承下去是多重继承

class Father(): 
    def talk(self):
        print("---爸爸的表达能力---")

class Mather():
    def smart(self):
        print("---妈妈聪明的头脑---")

class Child(Father,Mather):
    pass

child1 = Child()
child1.talk()
child1.smart()
#OUTPUT
---爸爸的表达能力---
---妈妈聪明的头脑---

四、导入类模块

import sys
导入sys模块 sys.path.append(‘work’)
将模块athlete.py添加到模块搜索路径
from athlete import *
导入athlete模块,使用athlete模块下的所有代码

import sys
sys.path.append('mywork')

# import athlete
# print(dir(athlete))
from athlete import *

如果有一个模块mymodule.py中也包含get_coach_data函数,该怎么区分这两个函数呢?
文件夹目录为:
work/p1/get_coach_data.py
work/p2/get_coach_data.py

import sys
sys.path.append('work')

from p1.mymodule import *
from p2.mymodule import *
import p1
import p2
p1.mymodule.demo()
p2.mymodule.demo()
#OUTPUT
p1 -- mymodule
p1 -- mymodule