|
发表于 2023-1-12 00:08:45
|
显示全部楼层
元类的应用
- # 一、给所有的类添加一个属性:
- class MetaC(type):
- def __new__(mcls, name, bases, attrs):
- attrs['author'] = 'fishc'
- return type.__new__(mcls, name, bases, attrs)
- class C(metaclass=MetaC):
- pass
- class D(metaclass=MetaC):
- pass
- c = C()
- d = D()
- print(c.author, d.author)# fishc fishc
- class MetaC(type):
- def __init__(cls, name, bases, attrs):
- cls.author = 'fishc'
- return type.__init__(cls, name, bases, attrs)
- class C(metaclass=MetaC):
- pass
- class D(metaclass=MetaC):
- pass
- c = C()
- d = D()
- print(c.author, d.author)# fishc fishc
- # 二、对类名的定义规范做限制
- class MetaC(type):
- def __init__(cls, name, bases, attrs):
- if not name.istitle():
- raise TypeError('类名必须为大写字母开头!')
- type.__init__(cls, name, bases, attrs)
- try:
- class mycls(metaclass=MetaC):
- pass
- except TypeError as e:
- print(e)# 类名必须为大写字母开头!
- # 三、修改对象的属性值 -> 如:把对象的所有字符串属性值都变成大写
- class MetaC(type):
- def __call__(cls, *args, **kwargs):
- new_args = [each.upper() for each in args if isinstance(each, str)]
- return type.__call__(cls, *new_args, **kwargs)
- class C(metaclass=MetaC):
- def __init__(self, name):
- self.name = name
- c = C('FishC')
- print(c.name)# FISHC
- # 当然如果传入的不是str就不显示
- class C(metaclass=MetaC):
- def __init__(self, *names):
- self.names = names
- c = C('FishC', 'Python', 1223)
- print(c.names)# ('FISHC', 'PYTHON')
- # 四、限制类实例化时的传参方式 -> 如:要求类在实例化对象时只能关键字参数传参
- class MetaC(type):
- def __call__(cls, *args, **kwargs):
- if args:
- raise TypeError('仅支持关键字参数~')
- return type.__call__(cls, *args, **kwargs)
- class C(metaclass=MetaC):
- def __init__(self, name):
- self.name = name
- try:
- c = C('fishc')
- except TypeError as e:
- print(e)# 仅支持关键字参数~
- c = C(name='fishc')
- print(c.name)# fishc
- # 五、禁止一个类被实例化
- class NoInstances(type):
- def __call__(self, *args, **kwargs):
- raise TypeError('该类禁止实例化!')
- class C(metaclass=NoInstances):
- pass
- try:
- c = C()
- except TypeError as e:
- print(e)# 该类禁止实例化!
- # 禁止实例化对象也可以使用静态方法和类方法
- class C(metaclass=NoInstances):
- @staticmethod
- def static_ok():
- print('静态方法允许使用~')
- @classmethod
- def class_ok(cls):
- print('类方法也允许使用~')
- C.static_ok()# 静态方法允许使用~
- C.class_ok()# 类方法也允许使用~
- # 六、只允许实例化一个对象
- class OnlyInstance(type):
- def __init__(cls, *args, **kwargs):
- cls.__instance = None
- type.__init__(cls, *args, **kwargs)
- def __call__(cls, *args, **kwargs):
- if cls.__instance is None:
- cls.__instance = type.__call__(cls, *args, **kwargs)
- return cls.__instance
- else:
- return cls.__instance
- class C(metaclass=OnlyInstance):
- pass
- c1 = C()
- c2 = C()
- print(c1 is c2)# True
- # c1和c2为同一个对象
- print(dir(C))
- # ['_OnlyInstance__instance', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
- # 对象被保存在类里边的_OnlyInstance__instance这个属性中
复制代码 |
|