虽然Python自己很难说是面向对象语言,但Python中的数据模型(data model)能够说真的是“纯面向对象”。在Python的世界里,一切皆是对象。不管是数值、字符串、序列、字典、函数、模块、类、实例、文件等等。html
元类(metaclass)是Python 2.2中引入的概念,它的做用是定制类的建立行为。这么解释可能有点难理解,那么这篇文章就经过实例,一步步解释Python中的元类。python
class Foo: def hello(self): print("hello world!") return foo = Foo() print(type(foo)) # <class '__main__.Foo'> print(type(foo.hello)) # <class 'method'> print(type(Foo)) # <class 'type'> temp = Foo # 赋值给其余变量 Foo.var = 11 # 增长参数 print(Foo) # 做为函数参数
例子中type(Foo)说明Foo自己也是一个对象,能够将其赋值给其余对象、对其添加属性、将其做为函数参数传递等等。正则表达式
在上边的例子中,类Foo的建立过程当中会执行class语句,此时须要首先肯定元类(元类定制类的建立行为)。元类的肯定过程以下:函数
上边的例子中,前2项都不符合,则直接使用默认元类type。即上边的语句至关于:ui
def hello(self): print("hello world") return Foo = type("Foo", (object,), {"hello": hello})
此时能够看出,实际上类Foo是元类type的实例。参见文章的封面图。spa
Python中的类能够动态建立,用的就是默认元类type。动态建立类的type函数原型为:code
type(object_or_name, bases, dict)
这里不过多赘述,上个章节中有介绍。举个比较复杂的动态建立类的例子:htm
def init(self, name): self.name = name return def hello(self): print("hello %s" % self.name) return Foo = type("Foo", (object,), {"__init__": init, "hello": hello, "cls_var": 10}) foo = Foo("xianhu") print(foo.hello()) print(Foo.cls_var)
再一次说明实例、类和元类之间的关系:对象
>>> foo.__class__ # <class 'Foo'> >>> Foo.__class__ # <class 'type'> >>> type.__class__ # <class 'type'>
foo是Foo的实例,Foo是type的实例,type的类又是type。type是默认的元类。那么如何自定义元类呢?(注意,百分之99的工程中不会用到自定义元类,除非你对元类很是理解)继承
举个例子,假设咱们须要对一个模块中的全部函数添加做者属性。首先自定义一个元类,自定义时,须要继承默认元类type,并重写其中的__new__方法:
class Author(type): def __new__(mcs, name, bases, dict): # 添加做者属性 dict["author"] = "xianhu" return super(Author, mcs).__new__(mcs, name, bases, dict)
对模块中全部函数的继承类参数中添加metaclass参数:
class Foo(object, metaclass=Author): pass foo = Foo() print(foo.author)
注意:Python3中再也不有__metaclass__属性以及模块级别的__metaclass__属性。若是一个模块中函数较多,能够利用正则表达式进行查找替换。
不过在平时的使用中,我发现了模块级别有个__build_class__函数,将其改成Author,就能达到模块级别元类的效果。但具体有哪些反作用还不太清楚,慎用!!!