Python 中type(name, base, dicts)與type.__new__(cls, name, base, dicts) 的區別

    看一個手寫metaclass的實現:html

# -*- coding:utf-8 -*-
# 2017/6/29


class Meta(type):
    def __new__(mcs, *args, **kwargs):
        print "Meta new"
        return type.__new__(mcs, "meta_class", (), {})  # 1
        # return type('meta_class', (), {})  # 2

    def __call__(cls, *args, **kwargs):
        return super(Meta, cls).__call__()
        # raise RuntimeError("initialize not allowed")


def base_class_with_meta(cls, *base):
    class metaclass(Meta):
        def __new__(mcs, *args, **kwargs):
            return Meta(mcs, base, kwargs)

    return type.__new__(metaclass, "temp_meta_class", base, {})


class A(base_class_with_meta(Meta)):
    def __new__(cls, *args, **kwargs):
        return super(A, cls).__new__(args, kwargs)

    def __init__(self, *args, **kwargs):
        super(A, self).__init__(args, kwargs)


a = A()
b = A()

    輸出python

D:\Python27\python.exe E:/workspace/lab_for_py/python-example-code/metaclass/test_metacalss_research.py
Meta new

Process finished with exit code 0

    看代碼註釋1和2局有什麼區別函數

    分析:spa

    type(name, base, dicts)會生成一個新類,類的__name__ 爲name, 基類爲base,命名空間爲__dict__code

不會調用類定義的init方法,此句返回是一個徹底的新類,和Meta沒有任何關係htm

    type.__new__(cls, name, base, dicts)會返回一個cls的instance,會調用init方法,此類爲Meta的實例對象

    附上文檔:utf-8

    https://docs.python.org/3/reference/datamodel.html?highlight=__new__#object.__new__文檔

    

    參考連接:get

    https://stackoverflow.com/questions/2608708/what-is-the-difference-between-type-and-type-new-in-python

    對元類的理解:

    在定義metaclass的時候__new__函數能夠控制類對象生成的過程,__init__函數能夠控制類對象的初始化,__new__和__init__  均可以控制類內參數(並不能控制類實例的參數),__call__函數能夠控制類實例化變量的過程,好比實現單例。

    搞這些東西的人,大家聽好了:

    Image result for 你他孃的真是我的才

相關文章
相關標籤/搜索