一、继承:简化代码避免重复复制
继承的意思相当于把父类中可以使用的方法写在自己类中一个性质复制
例1:创建一个人类,分男人类与女人类复制
属性:姓名、年龄
方法:吃、走 ====》公共特征
男:方法==》上班
女:方法==》洗衣服复制
class People: # 父类,可以理解为一个较为抽象的类,具体细分由下面的子类完成 # 公共代码放置位置 def __init__(self,name,age): self.name=name self.age=age def run(self): print('%s走路'%self.name) def eat(self): print('吃东西') # 继承People类:继承的意思相当于把以上可以使用的方法写在自己的类中一个性质 class man(People): # 男人类 def work(self): print('%s上班'%self.name) # 继承People类 class woman(People): # class woman(man): def watch(self): print('%s洗衣服'%self.name) # 实例化 xiaoming=man('小明',20) xiaoming.run() xiaoming.work() # xiaohua=woman('小花',19) xiaohua.run() xiaohua.watch() # xiaohua.work() # 不能访问小明的方法,子类之间的方法不可以互相访问,除非woman继承man类 # __bases__查看类继承的直接父级(通过类名) print(woman.__bases__) # (<class '__main__.man'>,) 继承 print(man.__bases__) # (<class '__main__.A'>,) 继承people print(People.__bases__) # (<class 'object'>,) # print(xiaohua.__bases__) # 错误写法复制
运行截图:
例2:多继承:
重写:当子类继承父类之后,如果子类不想使用父类的方法,可以通过重写来覆盖父类的方法复制
class base: def __init__(self,name,age): self.name=name self.age=age def run(self): print('%s走路'%self.name) def eat(self): print('吃东西') class Father(base): # 爸爸类 def work(self): print('%s上班'%self.name) def cook(self): print('%s做饭好难吃'%self.name) class Mother(base): # 妈妈类 def watch(self): print('%s洗衣服' % self.name) def cook(self): print('%s做饭真好吃'%self.name) # 如果Father在前面先继承Father类,优先级 class Son(Father,Mother): # 重写:当子类继承父类之后,如果子类不想使用父类的方法,可以通过重写来覆盖父类的方法 def cook(self): # pass print('%s做饭最好吃!!!'%self.name) xiaoming=Son('小明',20) # xiaoming.watch() xiaoming.work() xiaoming.run() xiaoming.eat() xiaoming.cook() # Father在前面先继承 print(Son.__mro__) # 查询类继承的顺序== 调用方法的时候依次查询 object是所有类的父类复制
运行截图:
例3:重写父类方法之后,如果又需要使用父类的方法呢?
super().money() # 如果自己的资金不够就把父类的也拿过来复制
super 函数可以调用父类的方法,在父类中也可以使用super函数
Father.cook(self) # 这样写先继承Father类===》可以理解准确性的继承复制
class base: def __init__(self,name,age): self.name=name self.age=age def run(self): print('%s走路'%self.name) def eat(self): print('吃东西') class Father(base): def work(self): print('%s上班'%self.name) def cook(self): print('%s做饭好难吃'%self.name) def money(self): print('爸爸有10万') class Mother(base): # 多继承 def watch(self): print('%s洗衣服' % self.name) def cook(self): print('%s做饭真好吃'%self.name) def money(self): print('妈妈有5万') class Son(Mother,Father): # 哪个在前面先继承哪个类 def cook(self): # 重写(新建一个新的类与父类方法名一样的时候),重写就不再使用父类的方法 # pass super().cook() # 在使用的重写的时候再去拿父级的方法,重写了的话就使用自己的 # super().watch() Father.cook(self) # 这样写先继承Father类===》可以理解准确性的继承 print('%s做饭最好吃!!!'%self.name) def money(self): super().money() # 如果自己的资金不够就把父类的也拿过来 Father.money(self) # 继承爸爸类 print('我有一万!!!') xiaoming=Son('小明',20) xiaoming.watch() xiaoming.work() xiaoming.run() xiaoming.eat() xiaoming.cook() # Mother在前面先继承 xiaoming.money() print(Son.__mro__) # 查询类继承的顺序== 调用方法的时候依次查询复制
运行截图:
二、魔术方法
思考:字符串拼接的时候,字符串可以直接相加,那我们自定义的类可以实现吗?
例1:
class Rectangle: # 英 [ˈrektæŋɡl] 长方形、矩形 def __init__(self,length,width): self.length = length self.width = width def __add__(self,other): # __add__两个实例相加的时候触发这个魔术方法 add_length = self.length + other.length add_width = self.width + other.width return add_length,add_width def Area(self): areas = self.length * self.width return areas # 实例a,b a = Rectangle(3,4) b=Rectangle(5,7) print(a+b) print(a.Area())
# 以上非重点内容,以下代码为重点内容复制
运行截图:
例2:str与repr知识点
1.在交互模式下输出的交互信息与 直接print的信息有些不同, 背后的原理是 ?
交互式模式使用repr方法
2.我们该如何使用这种机制 ?
3.类的实例可以向函数一样被调用吗?
正常情况下,实例是不能像函数一样被调用的,要想实例能够被调用,就需要定义 __call__ 方法
class Rectangle: # 类名后面可以不用括号 # class Rectangle(object): def __str__(self): # 打印实例名的时候会触发(自己调用)__str__方法 print(123) return '1232' # 只可以返回字符串,必须要有return # return 123 # 错误写法 # return [123] # 错误写法 # def __repr__(self): # 在开发时在调试的时候应用,即交互式模式下 # # return '1236666' # 只可以返回字符串,必须要有return # # print(123) # 错误写法,必须是字符串 def __call__(self, *args, **kwargs): # 实例名加括号会触发这个方法 print('123111100000000000') return '1231111' r = Rectangle() # 创建实例化 print(r) # str方法 print(r.__class__) # 查看类名 r() # call方法 print(r()) # print(123)复制
运行截图:
例3:常见的魔术方法
class Rectangle: ''' 对于类的注释一般写在这里,比如用户注册 账号: 密码: ''' name='小明' def __init__(self,age): self.age=age r = Rectangle(19) # 创建实例化 print(r.__dict__) # 查看全部属性,返回属性和属性值键值对形式 print(r.__doc__) # 查看对象文档,即类中(用三个引号引起来的部分) print(Rectangle.__bases__) # 查看父级 print(Rectangle.__mro__) # 查看多继承的顺序复制
运行截图:
练习题:
定义正方形类(继承矩形类),实现类的 实例可调用,调用时打印周长;
同时,直接 打印类实例 时能够打印出实例的面积复制
class Rectangle: # 英 [ˈrektæŋɡl] 长方形、矩形 def __init__(self,length,width): self.length = length self.width = width def Area(self): areas = self.length * self.width # return areas return '该面积为:%s'%areas # 正方形类 class Square(Rectangle): # 因为正方形只需一条边,所以需要重写__init__方法,满足自身需求 def __init__(self,width): self.width=width def __call__(self, *args, **kwargs): print('周长为:%s'%(self.width*4)) def __str__(self): return '面积为:%s'%(self.width*self.width) s=Square(5) s() # 实例调用触发 Call 方法 print(s) # 打印实例 ===》触发str方法复制
运行截图: