Python中的metaclass

<?xml version="1.0" encoding="gb2312"?>

pythonmetaclass

1 Python中的metaclass

metaclass翻译元类,即用来创建类的类。 在文档中的解释为

The class of a class. Class definitions create a class name, a class
dictionary, and a list of base classes. The metaclass is responsible for
taking those three arguments and creating the class. Most object oriented
programming languages provide a default implementation. What makes Python
special is that it is possible to create custom metaclasses. Most users never
need this tool, but when the need arises, metaclasses can provide powerful,
elegant solutions. They have been used for logging attribute access, adding
thread-safety, tracking object creation, implementing singletons, and many
other tasks.

1.1 metaclass的执行顺序

如:

class Test(metaclass=Meta):
    pass   

如果Meta和Test都有实现_new__init_函数,其直行顺序为Meta._new__, Meta._init__, Test._new__, Test._init__

看下面的例子:

class Meta(type):
    def __init__(self, name, bases, ns, **kwds):
        print('Meta.init', type(self), self)

    def __new__(self, name, bases, ns, **kwds):
        print('Meta.new', type(self), self, name, bases, ns, kwds)
        # type(self) = <class 'type'>,  self = <class '__main__.Meta'>
        # name = 'Test', bases = (object,)父类集合, ns = 类Test数据字典, kwds = 

        ret = super().__new__(self,name, bases, dict(ns))
        print('after Meta.new', type(ret), ret)
        # type(ret) = Meta, ret = Test # 类Meta,值Test
        return ret
print('*'*20)
class Test(object, metaclass=Meta):
    a = 1
    def __init__(self):
        self.b = 2
        print('Test.init', type(self), self)
        # type(self) = class Test, self = object Test

    def __new__(self, *args, **kwds):
        print('Test.new', type(self), self)
        # type(self) = Meta, self = Test 用Meta创建Test
        ret = super().__new__(self) # super() = object
        print('after Test.new', type(ret), ret)
        # type(ret) = class Test, ret = object Test
        return ret

print('-'*20)   
t = Test()
print(type(t), t)
print('='*20)

通过代码注释,大概知道了代码中各个变量的取值。在运行代码前,试试画出各个打印部分的顺序。上面已经说过Meta._new__, Meta._init__, Test._new__, Test._init_,那么*,-,=几行标志的顺序呢? 下面看执行结果:

********************
Meta.new <class 'type'> <class '__main__.Meta'> <class 'str'> (<class 'object'>,) {'a': 1, '__qualname__': 'Test', '__init__': <function Test.__init__ at 0x01E0A078>, '__module__': '__main__', '__new__': <function Test.__new__ at 0x01E0A0C0>} {}
after Meta.new <class '__main__.Meta'> <class '__main__.Test'>
Meta.init <class '__main__.Meta'> <class '__main__.Test'>
--------------------
Test.new <class '__main__.Meta'> <class '__main__.Test'>
after Test.new <class '__main__.Test'> <__main__.Test object at 0x01DF3E70>
Test.init <class '__main__.Test'> <__main__.Test object at 0x01DF3E70>
<class '__main__.Test'> <__main__.Test object at 0x01DF3E70>
====================   

从直行接过看,*在最先打印,而-打印在Meta直行后,可以看出,-之前的代码是创建class执行的,-之后的代码是创建实例执行的。

Date: 2013-07-18 22:41:39 中国标准时间

Author:

Org version 7.8.11 with Emacs version 24

Validate XHTML 1.0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值