小甲鱼 发表于 2022-12-25 22:23:46

第080讲:类和对象(XXIII)

0. 本节视频

https://www.bilibili.com/video/BV1c4411e77t?p=81


1. 温馨提示

如果在学习本节课的过程中遇到问题,可以在这个帖子下方提问哦~


Ensoleile 发表于 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 =
      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这个属性中
页: [1]
查看完整版本: 第080讲:类和对象(XXIII)