目录
继承
多继承
方法的重写和重用
重写
重用
__new__方法
单例模式
定制属性访问
描述符
装饰器
内置装饰器
使用继承可以方便代码的修改和管理,对于大量重复的代码可以将其放到一个父类中,在迭代更新时只需要修改这个父类中的一些代码块,而不是对于相同的代码逐条进行查找修改,这样既不方便,也容易遗漏出错。
语法
class 子类类名(父类类名): 子类的属性行为所有的类都是继承于object类, 在python3中object省略不写。如果所继承的父类和当前子类不在同一个作用域时,后面括号中写法为(模块名.父类类名)
继承的搜索顺序:先在当前类中搜索属性和方法,如果没有就回溯到自己的直接基类(父类),如果直接基类没有就逐层向上寻找。
多继承在定义子类的时候,子类名后面的括号中写多个基类名。
多继承在访问使用父类的属性方法时的搜索顺序,从括号中的第一个父类开始搜索的,如果所继承的这几个父类有同样的属性方法,访问使用也是先选择第一个。
当子类继承父类之后,如果子类不想使用父类的方法,或者父类的方法不能满足子类的需求,这时就需要对父类的方法进行重写,重写父类方法是在依然使用父类方法的方法名,只是将方法函数中的内容改写。重写后再调用这个方法时,父类的这个方法被覆盖,使用子类重新后的方法。
当子类重写父类的方法之后,还需要使用父类的这个方法的时候就是重用。重用父类方法的有两种方法:
class C(A,B): def play(self): # B.play(self) # 方法一:重新调用父类方法 super().play() # 方法二:使用重用方法的关键字函数super() print('正在吹牛皮')方法一:在重写方法下面重新调用父类的方法:父类名.调用方法函数(self)
方法二:使用重写的方法函数super():super().调用父类方法函数()
一般使用第二种方法,当父类类名或函数方法名发生改变的时候只需要在子类声明继承的括号中修改继承的父类类名即可。
查看类所继承的父类及以上类的继承顺序的方法:
使用类的mro方法或__mro__属性:
类名.mro() # 返回的结果为列表
类名.__mro__ # 返回的结果为元组
__new__方法也是一种魔法方法,__new__方法的作用是在实例化对象的时候为对象生成存储空间的,所以在类中最先被执行,且是自动被调用执行的。一般写在所有类方法之前。在调用__new__方法创建出一个实例之后,才会调用__init__方法初始化实例。__new__方法后的括号里的参数cls代表的是类的本身。__new__方法后面必须要有一个返回值object.__new__(cls),用来返回创建的类对象供后面的方法使用。
class A: def __new__(cls, *args, **kwargs): ''' :__new__创建类对象,返回的是类对象 :return 后面使用固定的写法object.__new__(cls),作用是返回这个"类的对象", 再让后面的方法调用这个对象,这个必须要有,不然后面方法没有可操作的对象。 ''' return object.__new__(cls) def __init__(self,name): self.name = name def __str__(self): return self.name a = A('小茗') print(a)__new__方法用来创建类对象,创建出来的每一个对象都有各自的存储空间,有时候我们需要创建这样一个对象,这个对象实例出来之后可以供多个变量使用,实际上就是一个对象有多个名字,通过打印使用不同变量名的这个对象的id,可以得到实例的内存地址相同。创建这种对象要用的方法为单例模式,固定写法:
def __new__(cls, *args, **kwargs): if not hasattr(cls,'instance'): cls.instance = super().__new__(cls) return cls.instance属性的增删改查
增改(下面的方法根据属性名判断,有则修改,无则添加)
对象名.属性名 = 属性值
setattr(对象名,属性名,属性值)
属性名.__setattr__(属性名,属性值)
删
delattr(对象名,属性名)
对象名.__delattr__(属性名)
del 对象名
查
hasattr(对象名,属性名) # 返回的是bool值
getattr(对象名,属性名) #返回属性值
对象名.__getattribute__(属性名) # 返回属性值,上面两个函数底层都是调用__getattr__
Python描述符是绑定行为的对象属性,支持重写方法来访问。描述符方法有:__get__(),__set__()和__delete__(),将描述符的类用在其他类中并作为其他类的实例属性使用。
__get__():对象被调用的时候返回
__set__():对象被修改(重新赋值)的时候被调用
__delete__():对象被删除的时候被调用
class Myclass: def __set__(self, instance): print('======set======') def __get__(self, instance, owner): print('======get=======') def __delete__(self, instance): print("=======delete=======") class My: m = Myclass() def __init__(self,name): self.name = name pass p = My('小白') del p.m
将函数以参数的方式传入到其他函数中被执行
def func_out(func): def func_in(): print('开始使用装饰器') func() print('结束使用装饰器') return func_in @func_out def func(): for i in range(5): print(i) func()
装饰器函数的基础:闭包
装饰器函数的使用:在需要使用装饰器的函数前使用 @装饰器函数名 的形式,将被装饰的函数以参数的形式传入到装饰器中被调用。
@property # 让方法像属性一样被使用,不需要像函数添加括号后才被调用。
@staticmethod # 静态属性方法,让实例和类断开联系,被装饰的函数中不需要传入实例对象self这个参数。因为和类断开联系,所以静态方法不能访问和修改实例属性。
@classmethod # 类方法,使用这个装饰器之后,被装饰函数中的参数需要传入cls参数,表示函数使用类对象。