python中的元类以及反射
一,元类
元类也是类,它是用来创建类的类
在默认情况下所有元类都是type
只要是继承了type 那么这个类就变成了一个元类。
自定义元类:
class MyType(type): def __init__(self,clss_name,bases,dict): super().__init__(clss_name,bases,dict) print(clss_name,bases,dict) if not clss_name.istitle(): raise Exception("你丫的 类名不会写...") # 为pig类指定了元类为MyType class Pig(metaclass=MyType): pass class Duck(metaclass=MyType): pass
二,元类中的call方法:
当你调用类对象时会自动执行元类中的__call__方法,并将这个类本身作为第一个参数传入。
覆盖元类中的call之后,这个类就无法产生对象,必须用super().__call__ 来完成对象创建,而且还要返回值
使用场景:
当想要控制对象的创建过程时,就会覆盖call方法。
当想要控制类的创建过程时,就会覆盖init 方法。
实现将对象的所有属性名称转为大写:4
lass MyType(type): def __call__(self, *args, **kwargs): new_args = [] for a in args: new_args.append(a.upper()) print(new_args) print(kwargs) return super().__call__(*new_args,**kwargs) class Person(metaclass=MyType): def __init__(self,name,gender): self.name = name self.gender = gender p = Person(name="jack",gender="woman") print(p.name) print(p.gender)
2.new 方法
当创建类对象时,会首先执行元类中的__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)
3.单例:
指的是一个类产生一个对象
单例是为了节省资源,当一个类的所有对象属性全部相同时,就没必要创建多个对象
元类实现:
# 单例n元类
class Single(type):
def __call__(self, *args, **kwargs):
if hasattr(self,"obj"): #判断是否存在已经有的对象
return getattr(self,"obj") # 有就返回
obj = super().__call__(*args,**kwargs) # 没有则创建
print("new 了")
self.obj = obj # 并存入类中
return obj
class Student(metaclass=Single):
def __init__(self,name):
self.name = name
class Person(metaclass=Single):
pass
# 只会创建一个对象
Person()
Person()
三,反射
反射指的是一个对象应该具备,可以检测,修改,增加自身属性的能力
反射其实就是通过字符串操作属性
1.hasattr:判断某个对象的某个属性是否存在
2.getattr:从某个对象中取出某个属性
3.setattr:给某个对象添加某个属性
4.delattr:从某个对象中删除某个属性