2016-12-27 12 views
2

每3.6.0文檔:提供__classcell__例如用於Python 3.6元類

CPython的實現細節:在CPython的3.6和後,__class__ 細胞傳遞給元類作爲一個__classcell__條目類 命名空間。如果存在,這必須傳播到調用type.__new__ 爲了正確初始化類。未能做到 ,因此將導致Python 3.6中的DeprecationWarning以及將來的 RuntimeWarning

有人可以提供一個這樣做的例子嗎?

一個實際需要它的例子嗎?

+0

一些想法:這個補丁有正確的關鍵詞(我不知道這個補丁是否成功):http://bugs.python.org/file44533/classcell.patch –

回答

4

如果您使用依賴於__class__的零參數super super().__method__(args),或者在類體內部引用__class__,則會引發此警告。

該文本實質上說的是,如果您定義了一個自定義元類並在將其傳遞到type.__new__之前篡改了您獲得的命名空間,則需要這樣做。您需要小心,並且始終確保您在metaclass.__new__中通過__classcell__type.__new__

也就是說,如果你創建一個新的花式命名空間讓人慾罷不能,經常檢查是否__classcell__在創建的原始命名空間中定義,並將其添加:

class MyMeta(type): 
    def __new__(cls, name, bases, namespace): 
     my_fancy_new_namespace = {....} 
     if '__classcell__' in namespace: 
      my_fancy_new_namespace['__classcell__'] = namespace['__classcell__'] 
     return super().__new__(cls, name, bases, my_fancy_new_namespace) 

您的評論鏈接的文件實際上是許多嘗試的補丁中的第一個,issue23722_classcell_reference_validation_v2.diff是從Issue 23722開始的最終補丁。

這樣做正確可以使用該修復這是在Python 3.6引入了一個問題,一個pull request made to Django可以看到的例子:

new_attrs = {'__module__': module} 
classcell = attrs.pop('__classcell__', None) 
if classcell is not None: 
    new_attrs['__classcell__'] = classcell 
new_class = super_new(cls, name, bases, new_attrs) 

__classcell__被簡單地添加到新的命名空間被傳遞到前type.__new__

+0

我花了一段時間才發現它如果類內的任何方法使用'super()'形式,則會創建它。 這可能是因爲之前無法調用任何會在元類方法本身內使用'super()'的類方法。更可能的是,Python 3.6中的新__init_subclass__機制需要它。 – jsbueno

+0

@jsbueno yup,'__init_subclass__'自定義元類,但。如果你使用'type'你很好。 –

+0

@ JimFasarakis-Hilliard能否提供一個參考或簡單的例子來說明自定義命名空間? –