多态 , 绑定方法与内置方法
1.3多继承
# 多继承 class DingYuan: def __init__(self): self.fatherName = "丁原义父" def setOffices(self): print("升官为主簿") class DongZhuo: def __init__(self): self.fatherName = "董卓义父" def setOffices(self): print("送赤兔马") class WangYun: def __init__(self): self.fatherName = "王允义父" def setOffice(self): print("送貂蝉") # class LvBu( DingYuan, WangYun , DongZhuo): def __init__(self): super(LvBu, self).__init__() def setOffices(self): WangYun.setOffice(self) DongZhuo.setOffices(self) DingYuan.setOffices(self) lvbu = LvBu() lvbu.setOffices() # mro就是看继承的顺序 print(LvBu.__mro__) print(DongZhuo.__mro__) # 只看父类顺序 print(LvBu.__bases__) # 同一个属性名遵守就近原则 print(lvbu.fatherName)
2、多态
一个对象的多种状态 不同的对象,调用同一个方法,表现出不同形式 多态的实现遵守两个原则:1.必须要有类的继承 2.子类必须重写父类的方法 什么时候多态 怎么方便怎么来
class Money: def ticke(self): print("车票单价") class Car(Money): def ticke(self): print("票价是200元") class Bus(Money): def ticke(self): print("票价150元") class Train(Money): def ticke(self): print("票价120元") c = Car() b = Bus() t = Train() c.ticke() b.ticke() t.ticke()
二 、绑定方法
1、绑定(类方法)
类方法, 通过装饰器@classmethod 进行装饰,绑定类cls 类方法操作一定是类属性,因为类方法无法通过self去获取对象属性
class Student: # 类属性 number = 0 def __init__(self, name): self.name = name def sleep(self): print(f"{self.name}在睡觉") @classmethod # 这个就是代表装饰类方法 # cls 是类本身 # 改变类属性是谁作用,类作用 def count(cls): cls.number += 1 return cls.number student1 = Student("笑脸") Student.count() student2 = Student("小虎同学") Student.count() student3 = Student("无风柳自断") Student.count() student4 = Student("爱丽丝") Student.count() print(Student.number) # 其中一个对象,也是和类是一样的 student5 = Student("学员1909") student5.count() print(Student.number)
2、静态方法(非绑定)
静态方法:通过装饰器@staticmethod进行装饰,为了方便代码统一管理,把类外面的某一个功能函数统一放到类里面管理,静态方法不能操作类的所有东西包括对象也是一样 单纯的一个方法:比如单纯的输出文字,单纯的计算某些数值,不改变任何属性 一句话,不需要用self,或者cls进行操作的都可以变成静态方法
import time class Student: # 类属性 number = 0 def __init__(self, name): self.name = name def sleep(self): print(f"{self.name}在睡觉") @classmethod # 这个就是代表装饰类方法 # cls 是类本身 # 改变类属性是谁作用,类作用 def count(cls): cls.number += 1 return cls.number @staticmethod def setTime(): print(f"{time.strftime('%Y-%m-%d')}") student1 = Student("笑脸") Student.count() student2 = Student("小虎同学") Student.count() student3 = Student("无风柳自断") Student.count() student4 = Student("爱丽丝") Student.count() print(Student.number) # 其中一个对象,也是和类是一样的 student5 = Student("学员1909") student5.count() print(Student.number) student5.setTime()
3、检查类型
type() # 查询单个数据类型 类如何查询类型 查询对象是否有指定的类生成 isinstance(obj/对象, cls/类) 查询是否有继承关系 issubclass(cls/子类,class_tuple/父类)
import time class Student: # 类属性 number = 0 def __init__(self, name): self.name = name def sleep(self): print(f"{self.name}在睡觉") @classmethod # 这个就是代表装饰类方法 # cls 是类本身 # 改变类属性是谁作用,类作用 def count(cls): cls.number += 1 return cls.number @staticmethod def setTime(): print(f"{time.strftime('%Y-%m-%d')}") student1 = Student("笑脸") Student.count() student2 = Student("小虎同学") Student.count() student3 = Student("无风柳自断") Student.count() student4 = Student("爱丽丝") Student.count() print(Student.number) # 其中一个对象,也是和类是一样的 student5 = Student("学员1909") student5.count() print(Student.number) student5.setTime() print(isinstance(student5, Student)) print(issubclass(Student, object))
三、内置方法
1.信息格式化方法
__str__该方法用户可以直接打印对象名来获取对象的描述,或者返回设计文本
class demo1: def __init__(self, name, age): self.name = name self.age = age # 这个内置方法是不需要手动调用 def __str__(self): return f"这个是{self.name}的对象" a = demo1("大聪明", 16) print(a)
2. 析构方法(魔法方法)
__del__ 当检测到对象每一继续被引用时,会自动删除对象所占用的内存空间 就算一大段代码没有涉及到对象的运用,也不会先自动删除,因为后面都有可能被引用对象 对象被间接赋值到另一个变量的时候,不能确保这个变量后续有没有继续被引用,那么不会删除
class Student: def __init__(self, name): self.name = name def func(self): print(f"{self.name}我还活着") # 基本不写这个东西的,默认执行 def __del__(self): # 当删除了对象后,就会自动运行这个代码 # 对象删除了,是不是所有对象代码失效了,但是你又想输出类输出某些东西,或者 # 运行某些东西的时候,可以写在del这边删除后再在执行代码, print(f"{self.name}gg了") # gg也可能是student1 student1 = Student("海绵宝宝") student1.func() print(student1) studentTest = student1 # student1.func() # # 为啥studnetTest,因为无法判断这个赋值的变量后面还能否使用,所以不能进行删除 # # __del__只作用类生成的对象,不能作用对象操作以外东西,就是亡语 # studentTest.func() studentTest.func() print("-"*100) print("-"*100) print("-"*100) print("-"*100)
__new__是内置的静态类方法,主要是给实例化对象分配内存空间,返回一个对象引用 python解析器在得到这个方法之后,会将引用作为第一个参数传递给init使用 如果没有返回值,python解析器没有获取对象的引用,就是创建不成功 new必须有返回值 拓展: new和init的相同点和不同点 相同点: 都可以实例化进行初始化 不同点:new不仅仅可以开辟内存空间吗,也可以实例化属性,init只能实例化对象,不能开辟内存空间 如果没有new设计约束,那么对象是可以无限创建,如果你想约束对象个数,要通过new进行约束
class A: # new怎么用 def __new__(cls, *args, **kwargs): print("给一个实例化对象分配一个内存空间") # super().__new__(cls) 作用就是生成对象,分配空间的参数 return super().__new__(cls) def __init__(self, name, age): self.name = name self.age = age a1 = A("xxx", 12) a2 = A("xxx", 12) a3 = A("xxx", 12) a4 = A("xxx", 12) a5 = A("xxx", 12)
class A: # 开始约束对象个数:1个 -》单例模式 # 隐藏类属性 # 这个有什么作用:做一个内存标志,None代表有空余的内存空间 # 如果有对象数据,就代表没有这个内存空间 # 为啥设置隐藏属性,就是只需要类内部操作,对象和外部不能操作 __instance = None def __new__(cls, *args, **kwargs): if cls.__instance is None : # super().__new__(cls) 这个就是返回创建对象的数据, 这里就是创建对象的意思 # cls.__instance = super().__new__(cls) 代表对象已经占用内层 cls.__instance = super().__new__(cls) return cls.__instance def __init__(self, name, age): self.name = name self.age = age a1 = A("梓良", 12) print(a1.name) # 这里应该会报错 a2 = A("xxx1", 15) print(a2.name)
class A: # 开始约束对象个数:1个 -》单例模式 # 隐藏类属性 # 这个有什么作用:做一个内存标志,None代表有空余的内存空间 # 如果有对象数据,就代表没有这个内存空间 # 为啥设置隐藏属性,就是只需要类内部操作,对象和外部不能操作 __instance = None __count = 1 def __new__(cls, *args, **kwargs): if cls.__instance is None or cls.__count <= 3 : # super().__new__(cls) 这个就是返回创建对象的数据, 这里就是创建对象的意思 # cls.__instance = super().__new__(cls) 代表对象已经占用内层 cls.__instance = super().__new__(cls) cls.__count += 1 return cls.__instance def __init__(self, name, age): self.name = name self.age = age a1 = A("梓良", 12) print(a1.name) # 这里应该会报错 a2 = A("xxx1", 15) print(a2.name) # 这里应该会报错 a3 = A("xxx2", 15) print(a3.name) # 这里应该会报错 a4 = A("xxx3", 15) print(a4.name)