簡體   English   中英

Python 2/3:為什么類型(Foo .__ init__)不同?

[英]Python 2/3: Why is type(Foo.__init__) different?

考慮一下類:

Foo(object):
    def __init__(self):
        pass

在Python 2上執行type(Foo.__init__)

Python 2.7.5 (default, Mar  9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> class Foo(object):
...     def __init__(self):
...             pass
...
>>> type(Foo.__init__)
<type 'instancemethod'>

在Python 3上執行type(Foo.__init__)

Python 3.4.1 (default, May 19 2014, 13:10:29)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> class Foo(object):
...     def __init__(self):
...             pass
...
>>> type(Foo.__init__)
<class 'function'>

為什么在Python 2和3上type(Foo.__init__)的返回值不同?

如果您要詢問更改了什么 ,則簡短版本位於3.0的新功能中

語言中刪除了“未綁定方法”的概念。 現在將方法作為類屬性引用時,您將獲得一個普通的函數對象。

更詳細地:

函數對象是描述符,__get__返回方法。 在Python 2.x中,它看起來像這樣(在純Python偽代碼中,略有簡化):

class FunctionType(object):
    # other stuff
    def __get__(self, instance, cls):
        return MethodType(func=self, instance=instance, cls=cls)

class MethodType(object):
    def __init__(self, func, instance, cls):
        self.__func__, self.__instance__, self.__class__ = func, instance, cls
    def __call__(self, *args, **kwargs):
        if self.__self__ is not None:
            return self.__func__(self.__self__, *args, **kwargs)
        else:
            return self.__func__(*args, **kwargs)

因此,當您編寫Foo.__init__ ,您將獲得未綁定的方法MethodType(__init__, None, Foo)

在3.x中,它看起來像這樣:

class FunctionType(object):
    # other stuff
    def __get__(self, instance, cls):
        if instance is not None:
            return MethodType(func=self, instance=instance)
        else:
            return self

class MethodType(object):
    def __init__(self, func, instance):
        self.__func__, self.__instance__, self.__class__ = func, instance, type(instance)
    def __call__(self, *args, **kwargs):
        return self.__func__(self.__self__, *args, **kwargs)

有關完整詳細信息,請參閱“可調用類型”下的3.x2.x的參考文檔中的標准層次結構。


如果您要問為什么更改它……據我所知,對此並沒有太多的討論—沒有PEP,也沒有關於python-dev或-ideas等的長期討論,並且僅給出了在文檔中一行。

但是推理似乎很明顯。 未綁定的方法並不是特別有用。 它們只是額外的腳手架,提供與它們包裝的功能完全相同的行為。*它們僅在2.2-2.7中存在,以更好地對經典類的行為進行建模**,並且/或者因為似乎更容易實現該方式和/或因為在設計初期,尚不清楚是否可以在沒有它的情況下實現@classmethod東西,並且當Guido變得足夠多以至於意識到那里沒有問題時,離開設計變得更容易,因為他是最初寫的。


*綁定方法的CPython實現添加了一個isinstance檢查,以驗證第一個參數是self.__class__ ,但是沒有明確記錄,沒有人依賴它編寫代碼,並且它對調試的幫助不如您會期望的。

**如果您想知道經典類為什么會如此工作,那么您必須瀏覽Guido的Python History博客-如果有時間,所有這些都值得一讀。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM