js css htmlPython

Python - metaclass,元类

2023-03-11  本文已影响0人  红薯爱帅

1. 概述

在Python中,继承于type的类,称之为元类metaclass。
设置一个class的metaclass为自定义元类MyMeta的话,该class的定义(注意,不是实例化)将由自定义元类MyMeta完成,其生命周期包含:

Animal和Cat类实例的构造初始化析构等函数,在Animal和Cat类中实现,而不是其元类MyMeta。

2. 示例

from inspect import isfunction


class MyMeta(type):
    # 解释器调用metaclass的new方法,来创建Animal和Cat类定义
    def __new__(cls, *args, **kwargs):
        _class = super().__new__(cls, *args, **kwargs)
        if _class.__name__ != 'Animal':
            if not hasattr(_class, 'run') or not isfunction(getattr(_class, 'run')):
                raise Exception('类{name}没有实现run方法'.format(name=_class.__name__))
        print('in meta new', args, kwargs)
        return _class

    # 解释器调用metaclass的init方法,来设置Animal或Cat的类属性
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.home = 'earth'
        print('in meta init', args, kwargs)

    # 实例化Animal或Cat时,调用至此
    # 可用于做唯一实例、实例个数控制等操作
    def __call__(self, *args, **kwds):
        instance =  super().__call__(*args, **kwds)
        print('in meta call', instance)
        return instance

    # 退出解释器进程时,会析构Animal和Cat类,而不是类实例,用途不大
    def __del__(self, *args, **kwargs):
        print('in meta del', args, kwargs)
        

class Animal(metaclass=MyMeta):
    def __init__(self, name):
        self.name = name


class Cat(Animal):
    def __new__(cls, *args, **kwargs):
        print('in cat new', cls, args, kwargs)
        return super().__new__(cls)

    def __init__(self, name):
        super().__init__(name)

    def run(self):
        print('run')

    # 类实例的析构
    def __del__(self, *args, **kwargs):
        print('in cat del', args, kwargs)


print('Animal class property', Animal.home)
print('Cat class property', Cat.home)
print('-'*30)

wild = Animal('wild')
print('Cat instance property', wild.name)
del wild
print('-'*30)

hh = Cat('huahua')
print('Cat instance property', hh.name)
del hh
print('-'*30)

Cat.classmethod_sleep = lambda : print(f'cat is sleeping')
Cat.self_sleep = lambda self: print(f'{self.name} cat is sleeping')
Cat.classmethod_sleep()
Cat('huahua').self_sleep()
print('-'*30)
in meta new ('Animal', (), {'__module__': '__main__', '__qualname__': 'Animal', '__init__': <function Animal.__init__ at 0x7f8dbf223af0>}) {}
in meta init ('Animal', (), {'__module__': '__main__', '__qualname__': 'Animal', '__init__': <function Animal.__init__ at 0x7f8dbf223af0>}) {}
in meta new ('Cat', (<class '__main__.Animal'>,), {'__module__': '__main__', '__qualname__': 'Cat', '__new__': <function Cat.__new__ at 0x7f8dbf223b80>, '__init__': <function Cat.__init__ at 0x7f8dbf223c10>, 'run': <function Cat.run at 0x7f8dbf223ca0>, '__del__': <function Cat.__del__ at 0x7f8dbf223d30>, '__classcell__': <cell at 0x7f8dbf32bc70: MyMeta object at 0x561ced380340>}) {}
in meta init ('Cat', (<class '__main__.Animal'>,), {'__module__': '__main__', '__qualname__': 'Cat', '__new__': <function Cat.__new__ at 0x7f8dbf223b80>, '__init__': <function Cat.__init__ at 0x7f8dbf223c10>, 'run': <function Cat.run at 0x7f8dbf223ca0>, '__del__': <function Cat.__del__ at 0x7f8dbf223d30>, '__classcell__': <cell at 0x7f8dbf32bc70: MyMeta object at 0x561ced380340>}) {}
Animal class property earth
Cat class property earth
------------------------------
in meta call <__main__.Animal object at 0x7f8dbf347820>
Cat instance property wild
------------------------------
in cat new <class '__main__.Cat'> ('huahua',) {}
in meta call <__main__.Cat object at 0x7f8dbf21ba60>
Cat instance property huahua
in cat del () {}
------------------------------
cat is sleeping
in cat new <class '__main__.Cat'> ('huahua',) {}
in meta call <__main__.Cat object at 0x7f8dbf21ba60>
huahua cat is sleeping
in cat del () {}
------------------------------
in meta del () {}
in meta del () {}
上一篇下一篇

猜你喜欢

热点阅读