Python 面向對象高階-----metaclass

Python 面向對象高階-----metaclass  

 前言

 類也是對象,既然類是對象,那就天然是某個東西的實例化,這個東西就是typepython

首先看下type是怎麼回事函數

type

type最經常使用的方法就是查看類型,這只是他的基礎用法罷了工具

>>> print(type(1))
<type 'int'>
>>> print(type("1"))
<type 'str'>
>>> print(type(ObjectCreator))
<type 'type'>
>>> print(type(ObjectCreator()))
<class '__main__.ObjectCreator'>

 type 經過傳入其餘參數也能夠實現類的建立spa

普通方式建立類:code

class Foo(object):
    bar = True

    def echo_bar(self):
        print(self.bar)

繼承關係的方式對象

class FooChild(Foo):
    pass

type 方式建立類:blog

def echo_bar(self):
    print(self.bar)

Foo = type('Foo', (), {'bar':True, 'echo_bar': echo_bar})

 有繼承關係方式繼承

FooChild = type('FooChild', (Foo, ), {})

以上兩種方法是等效的內存

type 的類建立方式的參數須要三個:字符串

  • 類的名字
  • 一組"類的父類"的元組(tuple) (這個會實現繼承,也能夠爲空)
  • 字典 (類的屬性名與值,key-value的形式,不傳至關於爲空,如通常寫法中的pass).

metaclass

說白了,函數 type 就是一個特殊的metaclass.
python在背後使用 type 創造了全部的類。type是全部類的metaclass.

 在python中,一切皆爲對象:整數、字符串、函數、類.全部這些對象,都是經過類來創造的.

    >>> age = 35
    >>> age.__class__
    <type 'int'>

    >>> name = 'bob'
    >>> name.__class__
    <type 'str'>

    >>> def foo(): pass
    >>> foo.__class__
    <type 'function'>

    >>> class Bar(object): pass
    >>> b = Bar()
    >>> b.__class__
    <class '__main__.Bar'>

__class____class__則就是由 type 來的了

    >>> age.__class__.__class__
    <type 'type'>
    >>> name.__class__.__class__
    <type 'type'>
    >>> foo.__class__.__class__
    <type 'type'>
    >>> b.__class__.__class__
    <type 'type'>

metaclass就是創造類對象的工具.若是你喜歡,你也能夠稱之爲"類的工廠".

type是python內置的metaclass。不過,你也能夠編寫本身的metaclass.

指定 metaclass

class Foo(metaclass=MyType):    # python 3 
  # __metaclass__ = MyType    # python 2 
  pass 

流程

Foo中有__metaclass__這個屬性嗎?

有:

  若是有,會在內存中經過__metaclass__建立一個名字爲Foo的類對象。

沒有:

  若是沒有__metaclass__,它會繼續在Bar(父類)中尋找,並嘗試作和前面一樣的操做。

  若是父類也沒有找到__metaclass__,它就會在模塊(module)中去尋找__metaclass__,並嘗試作一樣的操做。

  若是始終都找不到__metaclass__, 最終只能使用內置的type(這也是一個metaclass)來建立這個類對象。

自定義metaclass

 使用metaclass的主要目的,是爲了可以在建立類的時候,自動地修改類

 自定義 metaclass 首先就須要自定義一個不一樣於 type 的自定義 MyType,可以實現以前的 type 的類建立功能基礎上在實現其餘想要的功能

class MyType(type):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)

    def __call__(cls, *args, **kwargs):
        obj = cls.__new__(cls)

        cls.__init__(obj,*args, **kwargs)

        return obj

 

在建立類的時候指定 metaclass 爲 自定義的 MyType 便可

class Foo(object,metaclass=MyType):  # metaclass 指定由誰來建立這個類 
    a1 = 123
    def __init__(self):
        pass

    def __new__(cls, *args, **kwargs):
        return object.__new__(cls)

    def func(self):
        return 666

 那麼在此類建立實例的時候的流程是怎樣的呢?

foo = Foo()

 流程

建立類時

先執行 MyType 的 __init__ 方法 ,由super 轉向先執行 父類 type 的 __init__ 來建立類

類實例化時

當一個類在實例化時候,先執行 type 的 __call__ 方法 , __call__ 方法 的返回值就是實例化對象

__call__ 內部調用:

  類.__new__ 方法 :建立對象

  類.__init__ 方法 :對象初始化

相關文章
相關標籤/搜索