Python类(class)的那些事
什么是类的继承呢?
-
继承是一种新建类的方式
-
python中父类,子类(派生类),父类和子类只有在继承的时候才会产生
-
继承是为了拿到父类的所有东西
首先我们来看一个下面的函数
# 定义一个父类Parent_Foo他的属性有,姓氏、资产、车、房子 class Parent_Foo(): def __init__(self,first_name,money,car,house): self.first_name = first_name self.money = money self.car = car self.house = house def find_wife(self): print(f'{self.first_name}先生找到妻子白富美') # 定义类就要实例化来使用 # 显然我定义了一个pf的父类,他包括以下属性 pf = Parent_Foo('朱',10,'tesla','汤臣一品1102') # 他的子类继承父类的所有属性例如:first_name,money,car,house class Son_Foo(Parent_Foo): pass # 实例化类 sf = Son_Foo('朱', 10, 'tesla','汤臣一品1102') print(sf.first_name) print(sf.money) print(sf.car) print(sf.house) # 子类继承父类的属性,并且它里面的函数也可以调用,我们姑且当里面的函数为其特殊的技能,那么我们就得到了他都有的找妻子的技能,也可以在子类里面进行调用 sf.find_wife() # 可以直接调用
-
这里给出一个问题:为什么要继承?有什么作用
-
他的回答也很简单:减少重复,所有的父亲都可以用这个类,减轻复杂度,少写东西
-
不推荐使用继承!!!!(为什么?来看下面的程序)
class Animal(): def __init__(self,height,weight): self.weight = weight self.height = height def jiao(self): print(self.__class__.__name__,'叫') class Xingxing(): def sleep(self): print('sleep') class People(Animal,Xingxing): def read(self): print(self.__class__.__name__,'读书') class Dog(Animal): def eat_shit(self): print(self.__class__.__name__,'吃屎') aobama = People(170,120) aobama.jiao() aobama.sleep() meixi = People(185,150) meixi.jiao() DOG = Dog(30,40) DOG.jiao()
- 继承多个时候,功能与功能之间会混乱,顶多继承一个(不会重复写),继承后查找顺序:先自己,在类,在父类,在父类的父类
- 另一种解释就是继承是按照顺序的,他不能平级继承和越级继承,一旦继承多个那么程序就会混乱;
- 先把图的框架画出来,必须清晰完整
-
我们来看这个框架:可以看到其实我们上面的程序就是基于这个框架来编写的;
人、猪、狗都是子类、动物是父类,那么我们都可以继承父类里面的属性(height,weight)
以及他的技能(jiao)
当然我们自己也有独特的技能:sleep、read、eat_shit
牢记他的顺序:查找顺序:先自己,在类,在父类,在父类的父类
类的派生
为什么有派生呢?
首先,我们来看这样的问题:
class Foo:
def f1(self):
print('Foo.f1')
def f2(self): # self = b
print('Foo.f2')
self.f1() # b.f1
class Bar(Foo):
def f1(self):
print('Bar.f1')
b = Bar()
b.f2() # Foo.f2
print(b.__dict__) # b就是一个空字典{}
# 顺序:先自己,在类,在父类,在父类的父类
# 先自己没找到,然后去Foo找,有f2打印,调用f1注意这里的f1是self也就是他的传进来的b的f1
# 打印结果
Foo.f2
Bar.f1
{}
class Animal():
def __init__(self,height,weight):
self.weight = weight
self.height = height
def jiao(self):
print(self.__class__.__name__,'叫')
class Xingxing():
def sleep(self):
print('sleep')
class People(Animal,Xingxing):
def __init__(self,name,age):
self.name = name
self.age =age
def read(self):
print(self.__class__.__name__,'读书')
peo = People('mike',20) # 实例化的时候自动调用__init__
print(peo.__dict__)
# 打印结果为:
# {'name': 'mike', 'age': 20}
- 那么我们就发现了一个尴尬的问题:那就是我们定义的People并没有继承我们父类的Animal的属性,那我们的继承就失去了意义?
如何解决就引出了我们的派生: - 首先我们考虑这样的一个问题 我们在实例化的时候是不是可以这样操作
Animal.__init__(self,height,weight)# 对Animal类的__init__实例化,有init就调用,这里就是调用父类的init
那么我们就将上述代码修改为:
class Animal():
def __init__(self,height,weight):
self.weight = weight
self.height = height
def jiao(self):
print(self.__class__.__name__,'叫')
class Xingxing():
def sleep(self):
print('sleep')
class People(Animal,Xingxing):
def __init__(self,name,age):
self.name = name
self.age =age
def read(self):
print(self.__class__.__name__,'读书')
peo = People('mike',20)
Animal.__init__(peo,180,110) # Animal.__init__(self,height,weight)
print(peo.__dict__)
# 通过在People里面添加Animal的.__init__完成我们派生的目的
既然它可以放在外面那我们是不是也可以放在里面:
怎么做呢?
# 方法一:
class Animal():
def __init__(self,height,weight):
self.weight = weight
self.height = height
def jiao(self):
print(self.__class__.__name__,'叫')
class Xingxing():
def sleep(self):
print('sleep')
class People(Animal,Xingxing):
def __init__(self,name,age,height,weight):
# 'mike',20,180,110
Animal.__init__(self,height,weight)# Animal.__init__(peo,180,110)
self.name = name
self.age =age
def read(self):
print(self.__class__.__name__,'读书')
peo = People('mike',20,180,110)
print(peo.__dict__)
输出结果:
{'weight': 110, 'height': 180, 'name': 'mike', 'age': 20}
这样我觉得还是不简洁,还是很繁琐,这其实和最开始的实例化一样的,那我为什么还要称为派生呢:
那么我们来看看大佬们怎么做的:
# 方法1不需要继承也能做到
# 只适用于python3,而python2只能用第一种方法
# 即:super(People,self).__init__(height,weight)
class Animal():
def __init__(self,height,weight):
self.weight = weight
self.height = height
def jiao(self):
print(self.__class__.__name__,'叫')
class Xingxing():
def sleep(self):
print('sleep')
class People(Animal):
def __init__(self,name,age,height,weight):
# 'mike',20,180,110
super().__init__(height,weight) # 别人规定的语法
self.name = name
self.age =age
def read(self):
print(self.__class__.__name__,'读书')
peo = People('mike',20,180,110)
print(peo.__dict__)
o_o!!!
惊呆了,原来只需要将Animal.__init__(self,height,weight)
变成super().__init__(height,weight)
就可以了
当然这是python3
的用法,而python2
就需要看这个啦super(People,self).__init__(height,weight)
浅浅总结一下吧:
- 派生:继承父类属性的同时增加新的属性,然后使用
super.__init__()
类的组合:组合在一起
我们来玩一个选课系统:
- 先写框架:主要有学生、老师、管理员、课程类,那么人的父类就是People,课程可以不继承父类
- People类
- 学生类
- 老师类
- 管理员类
来看一下怎么操作的:
# 定义父类:people类
class People:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
# 学生类
class Students(People):
# 学生姓名,id,年龄,性别
def __init__(self,student__id,name, age, gender):
self.student__id = student__id # 学生特有属性id
super().__init__(name, age, gender) # 继承父类
def choose_course(self, course): # 特有技能
print(f'{self.name}选择{course.name}成功') # 这里的self就是特指Students.name
# 老师类
class Teacher(People):
# 老师姓名,性别,级别
def __init__(self, level, name, age, gender):
self.level = level
super().__init__(name, age, gender)
# 老师给某某学生什么课打分,那么我们需要学生名、课程和分数
def scored(self, student, course, score):
print(f'{self.name}老师给{student.name}课程{course.name}打{score}')
# 管理员
class Adamin(People):
# 创建课程
def create_course(self, course, name, price):
course = course(name, price)
print(f'管理员{self.name}创建了{course}')
return course
# 到这里我们发现没有课程,那么我们创建课程
class course:
def __init__(self, name, price):
self.name = name
self.price = price
# 实例化,类的对象
mike = Students('01', 'mike', 18, 'male')
jieke = Students('02', 'mike', 18, 'male')
# 老师
yy = Teacher('1', 'yy', '30',' male')
yyy = Teacher('2', 'yyy', '40', 'male')
# 管理员
sss = Adamin('sss',58,'male')
# 这样我们就将上面的人弄完了,但是选课是需要交互的
# 那么如何交互呢?
# 交互,学生选课,那么课程是管理员创建的,因此我们将代码修改为02版本
# 1、创建课程:把空列表python{}传到调用函数里面创建实例化对象,然后返回实例化对象python(有内容了)
# 01版本
# class Adamin(People):
# # 创建课程
# def create_course(self,course):
#
# print(f'管理员{self.name}创建了{course}')
# 修改后
# 02版本
# def create_course(self,course,name,price):
# course = course(name,price)
# print(f'管理员{self.name}创建了{course}')
# return course
python = sss.create_course(course, 'python', 8888)# 这里course是实例化对象
linux = sss.create_course(course, 'linux', 666)
print(python.__dict__)
print('*' * 50)
print(linux.__dict__)
# 学生选课要有课程,那么我们现在的代码呢?
# class Students(People):
# def __init__(self,student__id,name,age,gender):
# self.student__id = student__id
# super().__init__(name,age,gender)
# def choose_course(self,course):
# print(f'{name}选择{course}')
# 如何做呢?
# 修改后
# class Students(People):
# def __init__(self,student__id,name,age,gender):
# self.student__id = student__id
# super().__init__(name,age,gender)
# def choose_course(self, course): # python 对象
# self.course = course # 将上面创建的实例化对象传进来,就完成了,这就是组合
# print(f'{self.name}选择{course.name}')
# 2、选课程
mike.choose_course(python)
yy.scored(mike,python,'0')
# 当然我们还可以进行input,这样的操作
输出结果:
管理员sss创建了<__main__.course object at 0x000001C5FC0B1160>
管理员sss创建了<__main__.course object at 0x000001C5FAE5D2B0>
{'name': 'python', 'price': 8888}
**************************************************
{'name': 'linux', 'price': 666}
mike选择python成功
yy老师给mike课程python打0
总结:
- 弄清了什么是类的继承
- 弄清派生的方法
- 弄清类的组合方法
参考链接:
总结:
- 弄清了什么是类的继承
- 弄清派生的方法
- 弄清类的组合方法