2017-02-16 38 views
8

我正在嘗試使用python 3.6的新__init_subclass__功能(PEP 487)和abc模塊。它似乎沒有工作。下面的代碼:在Python 3.6中將ABCMeta與__init_subclass__結合起來時出現TypeError

from abc import ABCMeta 
class Initifier: 
    def __init_subclass__(cls, x=None, **kwargs): 
     super().__init_subclass__(**kwargs) 
     print('got x', x) 

class Abstracted(metaclass=ABCMeta): 
    pass 

class Thingy(Abstracted, Initifier, x=1): 
    pass 

thingy = Thingy() 

產生運行時執行以下操作:如果抽象不使用ABCMeta元類

Traceback (most recent call last): 
    File "<filename>", line 10, in <module> 
    class Thingy(Abstracted, Initifier, x=1): 
TypeError: __new__() got an unexpected keyword argument 'x' 

,一切工作正常。例如,下面的代碼仍然失敗,並出現類似的類型錯誤(大概是因爲元類'__new__在類實例化時運行,而父類'__new__不運行,直到對象實例化) 。

from abc import ABCMeta 

class Initifier: 
    def __new__(cls, name, bases, dct, x=None, **kwargs): 
     return super().__new__(cls, name, bases, dct, **kwargs) 

    def __init_subclass__(cls, x=None, **kwargs): 
     super().__init_subclass__(**kwargs) 
     print('got x', x) 

class Abstracted(metaclass=ABCMeta): 
    pass 

class Thingy(Initifier, Abstracted, x=1): 
    pass 

thingy = Thingy() 

任何人都可以證實,這是Python 3.6 abc模塊和/或__init_subclass__執行中的錯誤? (我可能會使用__init_subclass__錯誤。)有沒有人有解決方法?

+4

這是新'__init_subclass__'設計中的一個有趣的交互。幾乎所有現存的元類現在都應該將意外的關鍵字參數傳遞給'super().__ new__',所以'type .__ new__'可以將它們傳遞給'__init_subclass__',但是ABCMeta和其他許多元類不會這麼做。 – user2357112

+0

對於任何想將'__init_subclass__'和他們無法控制的元類一起使用的人來說,這可能會讓人頭疼。 – user2357112

+0

我希望這可以起作用,如果你逆轉繼承的順序,是否正確?由於'提取者'在'抽象'看到它之前會吃掉'x'。 –

回答

6

這是abc.ABCMeta中的一個錯誤,由於__init_subclass__設計中的疣。我建議報告它。

差不多存在每元類現在假設通過對super().__new__所以type.__new__可以將它們傳遞給__init_subclass__通過意想不到的關鍵字參數,但是ABCMeta大概噸的其他元類的不這樣做呢。 abc.ABCMeta.__new__關鍵字參數扼流器,而不是傳遞它,導致你看到的異常。

試圖使用__init_subclass__帶有尚未更新的新設計的元類的關鍵字參數不起作用。你必須等待你使用的元類被修補。

+0

謝謝。報告錯誤:http://bugs.python.org/issue29581 – So8res

相關問題