什么是继承,在生活中,子承父业,父亲和儿子就是继承的关系
在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方法,我无论你怎么定义这个类,你就是动物的一种形态,你这样才能用动物的方法,否则无法使用动物的方法
# 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
原文:https://www.cnblogs.com/geyatou322/p/11055053.html