# 一、给所有的类添加一个属性:
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这个属性中