格格小丫头
to be a new one ,believe yourself

类的继承

什么是继承,在生活中,子承父业,父亲和儿子就是继承的关系

在python中,父类和子类(派生类),父类和子类只有在继承的时候才会产生

以下面例子为例,继承为了拿到父类所有东西

class Parent_Poo:
    def __init__(self,first_name,money,car,house):
        self.first_name = first_name
        self.money = money*0.5
        print('继承财产扣掉一半')
        self.car = car
        self.house = house
        
    def find_wife(self):
        print('{self.first_name}先生找到妻子白富美')

        
class Son_Foo(Parent_Foo):
    pass

sf = Son_Foo('🐖',1000,'tesla','上海汤臣一品一栋')  # 实例化一个儿子对象
print(sf.first_name)
print(sf.money)
print(sf.car)
print(sf.house)
sf.find_wife()  # 因为sf 是一个对象,所有不用传find_wife的参数self,self是对象sf本身
Parent_Foo.find_wife(111) # Parent_Foo是一个类,类调用方法,需要传入参数self,可以随便什么值       

为什么要用继承: 减少重复,所有的儿子都可以用这个类,少写东西

# 人是动物,狗也是动物,我们就可以定义一个动物类,动物共同具有的特征
class Animal():  # 正常 class Animal: 就可以了,加() 结果一样,只是如果用继承的话,就加括号,并且括号内加入需要继承的类,可以多个
    def __init__(self,height,weight):
        self.height = height
        self.weight = weight
    def jiao(self):
        print(self.__class__.__name__,'叫')  # self.__class__.__name__打印的是类的名称

class Xingxing():
    def sleep(self):
        print('睡觉')

class People(Animal,Xingxing):
    def read(self):
        print('read')
        
    def jiao(self):
        print('jiao')
        
aobama = People(170,120) # 实例化对象,需要传入初始设置参数 height,weight
aobama.jiao() # jiao  属性查找顺序,先对象,再类,再父类,在父类的父类,菱形广义查找(python3)
aobama.sleep()
meixi = People(168,140)
meixi.jiao() # jiao 同上

class Dog(Animal):
    def eat(self):
        print('eat')
        
shinubi = Dog(40,50)
shinubi.jiao() #  print(self.__class__.__name__,'叫') 属性查找顺序

不推荐使用继承,当你继承多个的时候,功能和功能之间会混乱,顶多继承一个

继承后查找顺序: 先自己,再类,再父类,再父类的父类,不找多各类最后继承的同一个类,直接去找下一个父类,广度优先

下面做一个小练习,理解一个self参数的含义

class Foo:
    def f1(self):
        print('Foo.f1')
        
    def f2(self):
        print('Foo.f2')
        self.f1()
        
class Bar(Foo):
    def f1(self):
        print('Bar.f1')
        
        
b = Bar() #实例化一个对象
print(b.__dict__)   # {}  初始对象__dict__都为{}
b.f2()   # 想一想 打印结果什么?  b.f2()-->自己内部找,b中没有f2方法,去继承类Foo找-->找到Foo中的f2方法-->打印 Foo.f2-->执行self.f1()-->self 为对象本身b,实为b.f1()-->去b中找f1()-->能找到f1,打印Bar.f1
b.f2() # Foo.f2 Bar.f1

类的派生

class Animal():
    def __init__(self,height,weight):
        self.height = height
        self.weight = weight
        
    def jiao(self):
        print(self.__class__.__name__,'叫')
 
class XingXing():
    def __init__(self, gender):
        self.gender = gender

    def sleep(self):
        print('睡觉')

类的派生: 添加新的属性的同时还有继承父类的所有东西

print('*'*50)
# 方法一:
class People(Animal,Xingxing):
    def __init__(self,name,age) 
    self.name = name
    self.age = age
    
    def read(self):
        print('read')
        
    def jiao(self):
        print('jiao')
        
peo = People('gll',18) # 实例化的时候自动调用__init__
# 继承就是为了使用父类的属性
Animal.__init__(peo,180,140)
print(peo.__dict__)

# 这样使用起来非常麻烦

print('*'*50)

class People:
    def __init__(self,name,age,height,weight):   # 'gll', 18, 160, 110
        Animal.__init__(self,height,weight) # Animal.__init__(peo,160,110)
        self.name = name
        self.age = age
        
    def read(self):
        print('read')
        
    def jiao(self):
        print('jiao')
        
peo = People('gll',18,160,110) # 实例化的时候自动调用__init__
print(peo.__dict__)

# 发现: 方法一不需要继承也可以做到
print('*' * 50)
# 方法二:
class Xingixing(Animal):
    def __init__(self,weight,height,gender):
        super().__init__(weight,height)
        self.gender = gender
        
# 派生: 继承父类属性的同时增加新的属性,然后使用super.__init__()
# 引出方法二,方法二相当于对方法一进行了一层封装

class People(Xingxing):
    def __init__(self,name,age,height,weight,gender):
        super().__init__(height,weight,gender) # 别人规定的语法
        self.name = name
        self.age = age
        
    def read(self):
        print('read')
        
    def jiao(self):
        print('jiao')
peo = People('gll',18,160,110,'femal') # 实例化的时候自动调用__init__
print(peo.__dict__)
# 方法三:
print('*' * 50)
# python2中必须指定继承谁的__init__ (python2能用的,python3基本也是可以用)

class People(Animal):
    def __init__(self,name,age,height,weight):
        super(People,self).__init__(height,weight) # 别人规定的语法,python2中这样写
        self.name = name
        self.age = age
    def read(self):
        print('read')
        
    def jiao(self):
        print('jiao')
peo = People('gll',18,160,110) # 实例化的时候自动调用__init__
print(peo.__dict__)

类的组合

组合: 就是组合在一起
# 简单的选课系统
class People:
    def __init__(self,name,gender):
        self.name = name
        self.gender = gender
    def eat(self):
        print(f'{self.name}开始吃了')
        
        
class Student(People):
    def __init__(self,student_id,name,gender):
        self.student_id = student_id
        super(Student,self).__init__(name,gender)
    def choose_course(self,course): 
        self.course = course 
        print(f'{self.name}选课{course.name}成功')
        
class Teacher(People):
    def __init__(self,level,name,gender):
        self.level = level
        super(Teacher,self).__init__(name,gender)
     def score(self,student,course,score):
        print(f'老师{self.name}给{student.name}课程{course.name}打分{score}')
        
class Course:
    def __init__(self,name,price):
        self.name = name
        self.price = price
        
class Admin(People):
    def create_course(self,name,price):
        course = Course(name,price)
        print(f'管理员{self.name}创建了课程{name}')
        return course

# 课程
# python = Course('Python', '8888')
# linux = Course('Linux', '6666')

# 学生
zhubajie = Student('01', 'zhubajie', 'male')
sunwukong = Student('02', 'sunwukong', 'male')

# 老师
nick = Teacher('1', 'nick', 'male')
tank = Teacher('2', 'tank', 'female')

# 管理员
egon = Admin('egon', 'male')

# 业务逻辑

# 1. 创建课程
python = egon.create_course('python', '8888')
print(python.__dict__)
linux = egon.create_course('linux', '6666')
print(linux.__dict__)

# 2. 学生选择课程
zhubajie.choose_course(python)


# 3. 老师给学生打分
nick.scored(zhubajie,python,'0')

菱形继承问题

经典类 和新式类

在python3当中会默认继承object类

在python2当中不会默认继承object类,必须得自己手动添加

新式类: 只要继承了object类的就是新式类,python3当中所有的类都是新式类

经典类: 没有继承object类的就是经典类,只有python2当中的经典类

当继承为菱形继承的时候,经典类和新式类搜索某一个属性的顺序会不一样

class G:
    def test(self):
        print('from G')

class F(G):
    def test(self):
        print('from F')

class E(G):
    # def test(self):
    #     print('from E')
    pass

class D(G):
    def test(self):
        print('from D')

class C(F):
    def test(self):
        print('from C')


class B(E):
    # def test(self):
    #     print('from B')
    pass

class A(B, C, D):
    # def test(self):
    #     print('from A')
    pass

a = A()
a.test()
for i in A.__mro__:  # A.mro()
    print(i)    

在新式类中: 当遇到菱形继承时,会以广度优先查找

新式类

在经典类中: 当遇到菱形继承时,会以深度优先查找

经典类

普通继承就是正常顺序找

多态与多态性

多态: 多种状态,只要大家能继承同一种东西A,这些东西就是A的多态

水: 液态/固态/气态

动物: 人/够/猫

import abc

class Animal(metaclass = abc.ABCMeta): # 不推荐使用
    def __inint__(self,height,weight):
        self.height = height
        self.weight = weight
    
    def sleep(self):
        print('我在睡觉')
    @abc.abstractmethod
    def speak(self):
        print(self, '开始叫了')

    @abc.abstractmethod
    def eat(self):
        print(self, '开始吃了')


class People(Animal):
    def speak(self):
        print('开始叫了')

    def eat(self):
        print(self, '开始吃了')


class Dog(Animal):
    def speak(self):
        print('开始叫了')
    def eat(self):
        print(self, '开始吃了')


class Cow(Animal):
    def speak(self):
        print('开始叫了')
    def eat(self):
        print(self, '开始吃了')



class Foo(Animal):
    def speak(self):
        pass

f = Foo(1,2)  
f.sleep()
# 实例化对象
peo = People(180, 140)
dog = Dog(50, 100)
cow = Cow(100, 200)
# peo.speak()
# dog.speak()
# cow.speak()
# sheep.speak()
# mao.speak()

# peo.eat()
# dog.eat()

# 鸭子类型: 长得像鸭子,叫声也像鸭子,就是鸭子(只要有speak和eat这两个方法,那他就是动物类)
# 对于我们这个例子:你只要有speak方法/有eat方法,我无论你怎么定义这个类,你就是动物的一种形态,你这样才能用动物的方法,否则无法使用动物的方法   

dataclass的使用

# python 3.7 做的更新,定义类简单很多
from dataclasses import dataclass


@dataclass
class Point:
    x: float
    y: float
    z: float = 0.0


# p = Point(1.5, 2.5)
# print(p)  # produces "Point(x=1.5, y=2.5, z=0.0)"
from dataclasses import dataclass

@dataclass
class zhuangbei:
    price: int
    aggrev: int
    life_value: int

bc = zhuangbei(9,100,10)
class duolandun(zhuangbei):
    pass
class BlackCleaver(zhuangbei):
    pass
# print(bc)
f = BlackCleaver(0,100,10)
print(f)

查看dataclass的用法,可以参考下面的网址

dataclass使用:https://www.cnblogs.com/apocelipes/p/10284346.html

posted on 2019-06-19 21:54  格格小丫头  阅读(240)  评论(0编辑  收藏  举报