Python学习之路(37)——元类metaclass

首先,再次强调一点,在Python的世界里,一切皆对象。无论是数值、字符串、序列(包括列表、元组等)、字典、函数、模块、类和实例,甚至文件等等。

元类(metaclass)是从Python 2.2版本开始引入的,它是用于定制类的创建行为。

我们看一下创建类和实例的例子:

class Foo:
    def bar():
        print('hello python!')

foo = Foo()
print(type(foo))
print(type(foo.bar))
print(type(Foo))

temp = Foo
Foo.var = 11
print(Foo)


######执行结果######
<class '__main__.Foo'>
<class 'method'>
<class 'type'>
<class '__main__.Foo'>

注意,例子中的type(Foo)说明Foo本身也是一个对象(即“类”也是对象),可以将其赋值给其他对象,对其添加属性,将其作为函数参数传递等等。

上面的例子中,Foo类的创建过程会执行class语句,此时需要确定元类(元类定制类的创建行为)。确定元类的过程如下:

1)确定Foo类是否有参数__metaclass__,如果有,Python会在内存中通过__metaclass_-创建一个名为Foo的类对象,如果没有则

2)确定Foo类的父类是否有参数__metaclass__,并尝试做和第1步同样的工作,如果没有则

3)再向上确定Foo类的父类的父类是否有参数__metaclass__,并尝试做和前面一样的工作,如果没有则

4)使用默认元类type

上例中前2项都不符合,则直接使用默认元类type,则上面的语句相当于:

def bar(self):
    print('hello python!')
    return

Foo = type("Foo", (object,), {"bar": bar})
foo = Foo()
foo.bar()
print(type(Foo))
print(type(foo))
print(type(foo.bar))

######执行结果######
hello python!
<class 'type'>
<class '__main__.Foo'>
<class 'method'>

此时可以看出,实际上Foo类是元类type的实例。

 

动态创建类

 Python中的类可以动态创建(使用默认元类type),原型为:

type(object_or_name, bases, dict)

type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))

示例1:

def init(self, name):
    self.name = name
    return

def bar(self):
    print("hello %s" % self.name)
    return

Foo = type("Foo", (object,), {"__init__": init, "bar": bar, "cls_var": 10})
foo = Foo("nicolas")
print(foo.bar())
print(Foo.cls_var)


######执行结果######
hello nicolas
None
10

示例2:

#创建Foo类
Foo = type("Foo", (object,), {"bar": 10})

#继承Foo类
FooChild = type('FooChild', (Foo,), {})

print(FooChild)
print(FooChild.bar)

#给FooChild类添加方法
def hello(self):
    print("hello python!")

FooChild = type("FooChild", (Foo,), {"hello": hello})

hasattr(Foo, "hello")
hasattr(FooChild, "hello")

my_foo = FooChild()
my_foo.hello()


######执行结果######
<class '__main__.FooChild'>
10
hello python!

  

自定义元类

>>> foo.__class__     # <class 'Foo'>
>>> Foo.__class__     # <class 'type'>
>>> type.__class__    # <class 'type'>

foo是Foo的实例,Foo是type的实例,type的类又是type。type是默认的元类,我们如何自定义元类?

举个例子,假设我们需要对一个模块追踪的所有函数添加作者属性。首先自定义一个元类,自定义时,需要继承默认的元类type,并重写其中的__new__方法:

class Author(type):
    def __new__(mcs, name, bases, dict):
        # 添加作者属性
        dict["author"] = "nicolas"
        return super(Author, mcs).__new__(mcs, name, bases, dict)

对模块中的所有函数的继承类参数中添加metaclass参数:

class Foo(object, metaclass=Author):
    pass

foo = Foo()
print(foo.author)


######执行结果######
nicolas

  

注意:Python 3.x版本中不再有__metaclass__属性以及模块级别的__metaclass__属性。

posted on 2018-03-17 20:28  nicolas_Z  阅读(149)  评论(0)    收藏  举报

导航