笔记(二十二)

is a :如果A是B,那么B是A的基类(父类) base class

回顾:异常,层层继承

继承

格式:

class.Student(Person)

         pass

为什么要继承?继承概念引入

类里有很多重复的代码,都是人一类里的,把三者的共同特征和动作提取出来,迁移到Person类中,见下

class Person:  #父类
    def __init__(self):
        self.name='匿名'
        self.age=18
    def eat(self):
        print(self.name+'正在吃饭')
class Student(Person):  #子类
    pass
class Employee(Person):
    pass
class Doctor(Person):
    pass
s=Student()
s.eat()
'''
匿名正在吃饭
'''

父类为Person,子类为Student, Employee, Doctor。为无参情况

继承之后,父类的模板会给子类。调试时,s=Student()创建对象会进入Person类中的init,Student类中没有init,但父类有,执行父类的init、动作等

创建一个类,默认继承object,关系图如下

创建Student时,先找自己有没有,再一层一层往上找

Student()里有哪些东西?见下图

创建完类之后,s中有了内容

接着调用eat,Student类里没有,任进入Person类中的eat动作

总结

Student, Employee, Doctor--->都属于人类

有相同代码--->代码冗余,可读性不高

提取相同代码到Person类,Student, Employee, Doctor继承Person

继承中,父类有 init,子类也有init(Student里不再是pass,而是如下图),会出现什么情况?

能运行但会报阴影,不能运行s.eat()

报阴影原因

父类的__init__没有调用,如何调用父类的__init__?

class Person:  #父类
    def __init__(self):
        self.name='匿名'
        self.age=18
    def eat(self):
        print(self.name+'正在吃饭')
class Student(Person):  #子类
    def __init__(self):
        print('---student的init')
        super().__init__()  #super()父类对象
s=Student()
s.eat()
'''
---student的init
匿名正在吃饭
'''

super() -> same as super(__class__, <first argument>)

以上为无参数情况

有参数情况

父类init有参,子类调用父类init时就会报阴影,因为父类init有参,所以子类调用时也要传参

class Person:  
    def __init__(self,name):
        self.name=name
    def eat(self):
        print(self.name+'正在吃饭')
class Student(Person): 
    def __init__(self,name):
        print('--->student的init')
        super().__init__(name)
s=Student('tom')
s.eat()
'''
--->student的init
tom正在吃饭
'''

子类之间有各自不同的特征,如何表示?

class Person:  #父类
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def eat(self):
        print(self.name+'正在吃饭')
class Student(Person):  #子类
    def __init__(self,name,age,class1):
        super().__init__(name,age)
        self.class1=class1
class Employee(Person):
    def __init__(self,name,age,salary,manager):
        super(Employee, self).__init__(name,age)
        self.salary=salary
        self.manager=manager
class Doctor(Person):
    def __init__(self,name,age,patients):
        super(Doctor, self).__init__(name,age)
        #等同于super()__init__(name,age),多了一个判断,self属性是不是Doctor类型的
        #应该用这个
        self.patients=patients
s=Student('tom',18,'dian2012')  #班级就是学生类独有
e=Employee('yi',23,10000,'king')
lists=['zhangsan','lisi','wangwu']
d=Doctor('lucy',24,lists)

公共部分用super叫父类帮忙,自己的部分用self.xxx。虽然继承了Person,但又各自有各自的特点

能不能定义子类自己独有的动作?

class Person:  #父类
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def eat(self):
        print(self.name+'正在吃饭')
class Student(Person):  #子类
    def __init__(self,name,age,class1):
        super().__init__(name,age)
        self.class1=class1
    def study(self,course):
        print('{}正在学习{}课程'.format(self.name,course))

s=Student('tom',18,'dian2012') 
s.eat()
s.study('python基础')
'''
tom正在吃饭
tom正在学习python基础课程
'''

子类中有和父类同名的方法,函数重写,就近原则,先找自身有没有该动作,没有的话再往父类去找

class Person:  #父类
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def eat(self):
        print(self.name+'正在吃饭')
class Student(Person):  #子类
    def __init__(self,name,age,class1):
        super().__init__(name,age)
        self.class1=class1
    def study(self,course):
        print('{}正在学习{}课程'.format(self.name,course))
    def eat(self):
        super().eat() #还是能调用父类方法
        print(self.name + '正在吃饭,喜欢吃西兰花')
s=Student('tom',18,'dian2012'
s.eat('西兰花')
s.study('python基础')
'''
tom正在吃饭
tom正在吃饭,喜欢吃:西兰花
tom正在学习python基础课程
'''

 

特点总结

1.如果类中不定义__init__,调用父类 super class的__init__
2.如果类继承父类也需要定义自己的__init__,就需要在当前类的__init__调用一下父类__init__

3.如何调用父类__init__:
super().__init__(参数)
super(类名,对象).__init__(参数)
4.如果父类有eat(),子类也定义一个eat方法,默认搜索的原则:先找当前类,再去找父类s. eat()
overwrite:重写(覆盖)
父类提供的方法不能满足子类的需求,就需要在子类中定义一个同名的方法,这种行为叫做重写
5.子类方法中也可以调用父类方法:

super().方法名(参数)

练习

'''
编写一个简单的工资管理程序,系统可以管理以下四类人:工人(worker)、销售员(salesman)、经理(manager)、销售经理(salemanager)
所有的员工都具有员工号,姓名,工资等属性,有设置姓名,获取姓名,获取员工号,计算工资等方法。
1)工人:工人具有工作小时数和时薪的属性,工资计算法方法为工作小时数*时薪。
2)销售员:具有销售额和提成比例的属性,工资计算方法为销售额*提成比例。
3)经理:具有固定月薪的属性,工资计算方法为固定月薪。
4)销售经理:工资计算方法为销售额*提成比例+固定月薪。
请根据以上要求设计合理的类,完成以下功能:
1)添加所有类型的人员
2)计算月薪
3)显示所有人工资情况
'''
class Person:
    def __init__(self,no,name,salary):
        self.no=no
        self.name=name
        self.salary=salary
    #显示所有人工资情况
    def __str__(self):
        msg='工号:{},姓名:{},本月工资:{}'.format(self.no,self.name,self.salary)
        return msg
    def getSalary(self):
        return self.salary
class Worker(Person):
    def __init__(self,no,name,salary,hours,per_hour):
        super().__init__(no,name,salary)
        self.hours=hours
        self.per_hour=per_hour
    def getSalary(self):
        money=self.hours*self.per_hour
        self.salary+=money
        return self.salary
class Salesman(Person):
    def __init__(self, no, name, salary,salemoney,rate):
        super().__init__(no, name, salary)
        self.salemoney=salemoney
        self.rate=rate
    def getSalary(self):
        money=self.salemoney*self.rate
        self.salary+=money
        return self.salary
#创建子类对象
w=Worker('001','yu',2000,160,30)  #8h*20天
s=w.getSalary()
print('月薪是:',s)
print(w)
saler=Salesman('002','yuan',5000,5000000,0.003)
s1=saler.getSalary()
print(saler)
'''
月薪是: 6800
工号:001,姓名:yu,本月工资:6800
工号:002,姓名:yuan,本月工资:20000.0
'''

 注:提到的知识点

class Person:
    def __init__(self,name):
        self.name=name
    def eat(self):
        print('eat apple')
    def eat(self,food):
        print('eat ',food)
p=Person('tom')
p.eat()
'''
TypeError: eat() missing 1 required positional argument: 'food'
'''

就近原则,覆盖 

多重继承

class A:
    def test(self):
        print('--->AAA')
class B:
    def test1(self):
        print('--->BBB')
class C(A,B):
    def test2(self):
        print('--->CCC')
c=C()
c.test2()
c.test1()
'''
--->CCC
--->BBB
'''
class A:
    def test(self):
        print('--->AAA')
class B:
    def test(self):
        print('--->BBB')
class C(A,B):
    def test(self):
        print('--->CCC')
c=C()
c.test()
'''
--->CCC
'''
class Base:
    def test(self):
        print('---base---')
class A(Base):
    def test(self):
        print('--->AAA')
class B(Base):
    def test(self):
        print('--->BBB')
class C(Base):
    def test(self):
        print('--->CCC')
class D(A,B,C):
    pass
d=D()
d.test()
import inspect
print(inspect.getmro(D))
print(D.__mro__)
'''
--->AAA
(<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, 
<class '__main__.C'>, <class '__main__.Base'>, <class 'object'>)
(<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, 
<class '__main__.C'>, <class '__main__.Base'>, <class 'object'>)
'''

def getmro(cls):
    "Return tuple of base classes (including cls) in method resolution order." 按顺序搜索
    return cls.__mro__

多继承的搜索顺序:经典类  新式类

经典类:广度优先    新式类:深度优先      python3为经典类

 

顺序应该是这样:D-C1-P1-object,然后退回到C1,C1-P2,再退回到D,D-C2

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
某公司雇员(Employee)包括经理(Manager),技术人员(Technician)和销售员(Salesman)。开发部经理(DeveloperManger),既是经理也是技术人员。销售部经理(SalesManager),既是经理也是销售员。 以Employee类为虚基类派生出Manager,Technician和Salesman类;再进一步派生出Developermanager和Salesmanager类。 Employee类的属性包括姓名、职工号、工资级别,月薪(实发基本工资加业绩工资)。操作包括月薪计算函数(pay()),该函数要求输入请假天数,扣去应扣工资后,得出实发基本工资。 Technician类派生的属性有每小时附加酬金和当月工作时数,及研究完成进度系数。业绩工资为三者之积。也包括同名的pay()函数,工资总额为基本工资加业绩工资。 Salesman类派生的属性有当月销售额和酬金提取百分比,业绩工资为两者之积。也包括同名的pay()函数,工资总额为基本工资加业绩工资。 Manager类派生属性有固定奖金额和业绩系数,业绩工资为两者之积。工资总额也为基本工资加业绩工资。 而DeveloperManager类,pay()函数是将作为经理和作为技术人员业绩工资之和的一半作为业绩工资。 SalesManager类,pay()函数则是经理的固定奖金额的一半,加上部门总销售额与提成比例之积,这是业绩工资。 编程实现工资管理。特别注意pay()的定义和调用方法:先用同名覆盖,再用运行时多态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值