Python类的__new__,__init__,__getitem__,__setitem__,__setattr__,__getattr__等魔术方法

发布时间:2024-06-08 09:01

class my_meta(type):
    def __init__(self, *args):
        print(\'__init__\')

    def __call__(self, *args, **kwargs):
        print(\'__call__\')
        return super(my_meta, self).__call__()

    def __new__(cls, *args, **kwargs):
        print(\'__new__\')
        return super(my_meta, cls).__new__(cls, *args, **kwargs)


class T(metaclass=my_meta):
    def __init__(self):
        print(\"init\")
        pass

    def __call__(self, *args, **kwargs):
        print(\"call\")

    def __new__(cls, *args, **kwargs):
        print(\"new\")
        return super().__new__(cls, *args, **kwargs)

    def __setattr__(self, key, value):
        print(\'setattr\')
        super(T, self).__setattr__(key, value)

    def __getattr__(self, item):
        print(\'getattr\')
        return self.__dict__.get(item)

    def __setitem__(self, key, value):
        print(\'setitem\')
        super(T, self).__setattr__(key, value)

    def __getitem__(self, item):
        print(\'getitem\')
        return self.__dict__.get(item)

    def __getattribute__(self, item):
        print(\'get_attribute\')
        return super(T, self).__getattribute__(item)

if __name__ == \'__main__\':
    t = T()
    print(\'-\' * 90)
    t.name = \'z\'
    t[\'nn\'] = \'nn\'
    print(t.nn)
    print(\'x\'*99)
    print(t.nn)
    print(t[\'nn\'])
    print(\'-\' * 90)
    print(t.z)
    # print(t[\'z\'])

程序运行结果为

__new__
__init__
__call__
new
init
------------------------------------------------------------------------------------------
setattr
setitem
get_attribute
nn
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
get_attribute
nn
getitem
get_attribute
nn
------------------------------------------------------------------------------------------
get_attribute
getattr
get_attribute
None

    接下来来分析结果,首先,类是由元类(metaclass)创建的,当Python解释器运行到 class T时,会调用元类的__new__()来创建一个类,然后调用__init__()实例化对象,这个就是T类。当解释器执行到 t=T()时,类名加括号会调用元类的__call__()方法(因为T是由my_meta创建的,T是它的一个实例,实例加括号会调用它类的call方法),再调用类的__new__创建、__init__初始化并返回创建的实例,也就是t。

    类实例的所有属性都会保存在__dict__中。

    当使用 类实例.xx时(t.xx)会调用类的__getattribute__()函数,如果报错或者为找到则会继续调用getattr方法,xx会当作getattr函数的key参数传进去。

    类实例[\'xx\'](t[\'xx\'])会调用getitem方法,参数与getattr一致,当未找到值时也调用__getattribute__方法。

    使用赋值语句时(t[\'xx\']=\'xx\' \\ t.xx=‘xxx\')会调用对应的set方法(setitem或setattr)setattr可调用父类的setattr来将值设置进去。

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号