什么是反射, 其实是反省,自省的意思
反射指的是一个对象应该具备,可以检测,修改,增加自身属性的能力
反射就是通过字符串操作属性
涉及的四个函数,这四个函数就是普通的内置函数 没有双下划綫,与print等等没有区别
class Person: def __init__(self,name, age, gender): self.name = name self.age = age self.gender = gender p = Person('cly', 17, 'female') print(hasattr(p, 'salary')) # 判断对象中是否存在某个属性 print(getattr(p, 'ages', None)) # 从对象中取出属性,第三个值位默认值 当属性不存在是返回默认值 # 为对象添加属性 setattr(p, 'salary', 1000000000) # 删除对象属性 delattr(p, 'salary')
反射其实就是对属性的增删改查,但是如果直接使用内置的dict来操作,语法繁琐,不好理解
另外一个最主要的问题是,如果对象不是我自己写的是另一方提供的,我就必须判断这个对象是否满足的要求,也就是是否我需要的属性和方法
所有的类都是对象
所有的类都是元类产生的
object是根类,是所有类的父类
默认情况下所有类都是元类
学习元类的目的:
高度自定义一个类,例如控制类的名字必须以大驼峰的方式来书写
类也是对象,也有自己的类
我们的需求是创建类对象并做一些限制
我们可以找到类对象的类(元类)进行覆盖其中init方法就能实现需求
当然我们不能改变源代码,所以应该继承type来编写自己的类,同时覆盖init来完成需求
# 继承type元类 # 定义了一个类 class A(type): def __init__(self,class_name,bases,dict): super().__init__(class_name,bases,dict) self.name = class_name if not self.name.istitle(): raise Exception # 为asd类指定了元类为A class asd(metaclass=A): pass
元类中call方法
当你调用类对象时会自动珍惜元类中的__call__方法 ,并将这个类本身作为第一个参数传入,以及后面的一堆参数 覆盖元类中的call之后,这个类就无法产生对象,必须调用super().__call__来完成对象的创建 并返回其返回值
使用场景
当你想控制对象的创建过程时,就覆盖call方法
当你想控制类的创建过程时,就覆盖init方法
案例:
class Mytype(type): def __call__(self, *args, **kwargs): l = [] for i in args: l.append(i.upper()) return super().__call__(*l, **kwargs) class Person(metaclass=Mytype): def __init__(self, name, gender): self.name = name self.gender = gender p = Person('cly','man') print(p.__dict__)
当你要创建对象时,会首先执行元类中的__new__方法,拿到一个空对象,然后会自动调用 __init__来对这个类进行初始化操作 注意:如果你覆盖了该方法则必须保证,new方法必须有返回值且必须是对应的类对象
class Meta(type): def __new__(cls, *args, **kwargs): print(cls) # 元类自己 print(args) # 创建类需要的几个参数 类名,基类,名称空间 print(kwargs) #空的 print("new run") # return super().__new__(cls,*args,**kwargs) obj = type.__new__(cls,*args,**kwargs) return obj def __init__(self,a,b,c): super().__init__(a,b,c) print("init run") class A(metaclass=Meta): pass print(A)
单例设计模式
单例:指的是一个类产生一个对象
为什么要用单例?
单例是为了节省资源,当一个类的所有对象属性全部相同时,则没有必要创建多个对象
元类实现:
class Mytype(type): def __call__(self, *args, **kwargs): if hasattr(self, 'obj'): # 判断对象是否已存在对象 return getattr(self,'obj') obj = super().__call__(*args, **kwargs) # 没有对象就创建一个 self.obj = obj # 存入类中 return obj class Person(metaclass=Mytype): def __init__(self,name,age): self.name = name self.age = age p = Person('cly', 18) p1 = Person('asd','asd') # 只会存在一个对象 print(p1.__dict__)