python的元类

类是用来生成实例的模板,而元类则是用来生成类的模板。

在 Python(以及其它语言)中,类本身就是可以被传递和自省的对象。正如前面所讲到的,既然可以用类作为模板来生成对象,那么用什么 作为模板来生成类呢?答案当然是 元类(metaclass)

python 2.2+以后提供了一个称为type的特殊类,它是一个类工厂。

使用type创建新类:

>>> X = type('X', (), {'foo': lambda self: 'foo'})
>>> X, X().foo()
(<class '__main__.X'>, 'foo')

X就是type创建的类。

可以用来使用type的子类,来创建新类:

 1 class ChattType(type):
 2     def __new__(cls, name, bases, dct):    # __new__函数创建 3         # 在__new__方法里,cls是ChattType类本身
 4         # name是类的名称,字符串
 5         # bases是类的基类,一个tuple
 6         # dct是附件到类上的属性和方法,是一个字典
 7         
 8         print "Allocating memory for class", name
 9         print "cls is: ", cls
10         print "name is: ", name
11         print "bases is: ", bases
12         print "dct is: ", dct
13         print
14         return type.__new__(cls, name, bases, dct)  # 创建类
15     
16     def __init__(cls, name, bases, dct):    # __init__函数初始化17         # 在__init__方法里,cls是已经创建好的类
18         # name, bases, dct属性和__new__方法相同
19     
20         print "Initing class", name
21         print "cls is: ", cls
22         print "name is: ", name
23         print "bases is: ", bases
24         print "dct is: ", dct
25         print
26         super(ChattType, cls).__init__(name, bases, dct)
27 
28     def some_func(cls):
29         print "cls is: ", cls
30         print
31         # 在这里,cls是已经生成好的类
32         # 将类方法附件到生成的类上
33         return "i am some_func in metaclass."
34 
35 X = ChattType('X', (), {'foo': lambda self: 'foo'})
36 
37 # 创建好的X类
38 print X
39 print
40 
41 # 类X的some_func方法
42 print X.some_func()
43 print
44 
45 # 类X的实例的foo方法
46 print X().foo()
47 print
48 
49 # 调用类X的实例的some_func方法会报错!!!
50 print X().some_func()


下面是运行结果:

Allocating memory for class X
cls is:  <class '__main__.ChattType'>
name is:  X
bases is:  ()
dct is:  {'foo': <function <lambda> at 0x7f4f54b96668>}

Initing class X
cls is:  <class '__main__.X'>
name is:  X
bases is:  ()
dct is:  {'foo': <function <lambda> at 0x7f4f54b96668>}

<class '__main__.X'>

cls is:  <class '__main__.X'>

i am some_func in metaclass.

foo

Traceback (most recent call last):
  File "meta_class.py", line 53, in <module>
    print X().some_func()
AttributeError: 'X' object has no attribute 'some_func'

注意:

在__new__方法中,第一个参数cls表示的元类的子类本身,就是ChattType。

而在__init__方法中,第一个参数cls表示已经创建好的类。

 

但是像下面这种情况下,在类中使用__new__则情况不同:

class t(object):
   # __new__函数创建实例
def __new__(cls, *args, **kwargs): print "cls is: ", cls print "args is: ", args print "kwargs is: ", kwargs #return super(t, cls).__new__(cls, *args, **kwargs) return object.__new__(cls, *args, **kwargs)

   # __init__函数初始化实例
def __init__(self): print "init"

 

运行结果:

cls is:  <class '__main__.t'>
args is:  ()
kwargs is:  {}
init

在类的__new__方法里,cls参数是类本身。

 

原文地址:https://www.cnblogs.com/huazi/p/2796602.html