2019新年快乐 - 学习python的“元类”

1学习的原文:What are metaclasses in Python

时刻牢记:python是面向对象的,才能理解python的“元类”

    理解python元类的概念之前,一定要时刻牢记python是面向对象的,也就是说,python中,一切都是对象,整数是对象、字符串是对象、函数也是对象,类的实例更是对象。

>>> age = 47
>>> type(age)
<class 'int'>
>>> age.__class__
<class 'int'>
>>> city = 'shenyang'
>>> city.__class__
<class 'str'>
>>> type(city)
<class 'str'>
>>> 

    python中,类(class)也是对象!

class ObjectCreator(object):
...   pass

    当python解释器看到定义类的关键字“class”时,在内存中创建一个名称为类名(ObjectCreator)的“对象”,这个对象(类)自身能创建一个对象(这个类的实例),因此这也就证明了这个“对象”就是个“类”。而且因为这个 “类”同时也是个对象,所以这个对象(类)可以:
        - 被赋值给一个变量
        - 可以复制(copy)
        - 可以给它增加属性
        - 可以作为一个函数的参数被传递
        - 类的定义代码不一定非得写在“外面”,它可以写在函数内部!
    上面这段话有些绕嘴,但它是理解“元类”这个概念的基础:python中的类不仅仅是一段定义类的代码,它本身就是存在于内存中的一个对象,这个对象可以被用来创建其它的类(子类)。

>>> def choose_class(name):
...     if name == 'foo':
...             class Foo(object):
...                     pass
...             return Foo #return the class, not an instance
...     else:
...             class Bar(object):
...                     pass
...             return Bar
... 
>>> MyClass = choose_class('foo')
>>> print (MyClass)
<class '__main__.choose_class.<locals>.Foo'>
>>> MyClass = choose_class('bar')
>>> print (MyClass)
<class '__main__.choose_class.<locals>.Bar'>
>>> print (MyClass())
<__main__.choose_class.<locals>.Bar object at 0x108dea4e0>

    那么,问题是:既然类是对象,那谁来创建这个对象?这个对象有没有父类?
    答案是:type产生类!
    “type”函数除了能返回“对象”的“类”型之外。还是python用来动态产生“类”的函数。语法如下:

type(name of the class,
     tuple of the parent class (for inheritance, can be empty),
     dictionary containing attributes names and values)

    例如,下面这个类,通常的定义是:

>>> class MyShinyClass(object):
...       pass

    使用type而不是上面的代码产生MyShinyClass类的方法如下:

>>> MyShinyClass = type('MyShinyClass', (), {}) # returns a class object
>>> print (MyShinyClass)
<class '__main__.MyShinyClass'>
>>> print(MyShinyClass()) # create an instance with the class
<__main__.MyShinyClass object at 0x108dea2e8>
>>> 

    也就是说,python解释器将类定义的代码动态的用type在内存中生成一个对象。

元类 metaclass

    阅读如上所述的python创建类的过程可以得出结论:“类”也是个对象,那这个对象肯定是某个类的实例(对象),而这个“某个类”就是所谓的“元类(metaclass)”,也就是说,元类是所有类的类,是所有类的“父类”,这个元类(metaclass)就是“type”!“type”就是python的内嵌的“元类(metaclass)”!

>>> age = 45
>>> age.__class__
<class 'int'>
>>> name = 'bob'
>>> name.__class__
<class 'str'>
>>> def foo(): pass
... 
>>> foo.__class__
<class 'function'>
>>> class Bar(object): pass
... 
>>> b = Bar()
>>> b.__class__
<class '__main__.Bar'>
>>> age.__class__.__class__
<class 'type'>
>>> name.__class__.__class__
<class 'type'>
>>> foo.__class__.__class__
<class 'type'>
>>> b.__class__.__class__
<class 'type'>
>>> 

    看到了吧,type就是python所有对象(类)的“元类”,它定义了python所有类(内置或自定义)创建时所需做的默认操作,也正是因为这样,python中可以自定义“元类”。

创建自己的元类

    创建自己的元类的目的,是增加一些“在类创建时的默认操作”。
    python2中自定义元类的代码:

class Foo(object):
	__metaclass__ = something...

    这个something可以是anything,通常是一个完成特定功能的函数。
python3中自定义元类的代码:

class Foo (object, metaclass = something):
	[...]

注意:
原文中有这么一段话:
Be careful here that the metaclass attribute will not be inherited, the metaclass of the parent (Bar.class) will be. If Bar used a metaclass attribute that created Bar with type() (and not type.new()), the subclasses will not inherit that behavior.
这段话字面意思是:__metaclass__这个,“特性”是不能被继承的,能被继承的是这个类的父类的元类。这句话也有些“混沌”,大概的意思就是:__metaclass__不是一个公开的可以被子类继承的“属性”,它只是这个“类”用来实现自定义“元类”的一种实现手段。或者干脆这么理解:__metaclass__不是面向对象编程概念中的“属性(property)”,是父类的私有特性。


  1. What are metaclasses in Python? ↩︎

猜你喜欢

转载自blog.csdn.net/steventian72/article/details/85534733