鱼C论坛

 找回密码
 立即注册
查看: 1152|回复: 1

[知识点备忘] 第080讲:类和对象(XXIII)

[复制链接]
发表于 2022-12-25 22:23:46 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
0. 本节视频




1. 温馨提示

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


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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这个属性中
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 3 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 02:53

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表