簡體   English   中英

正確的 mro 訂單屬性 object 找不到抽象屬性

[英]Correct mro order attrs object can't find abstract property

以下運行良好:

from abc import ABC, abstractmethod
import attr

class A(ABC):
    @abstractmethod
    def prop(self):
        pass

    def foo(self):
        print(self.prop())

class B:
    def prop(self):
        return 5

class C(B, A):
    pass

C()

在這里, C有一個從B繼承的 function prop ,該道具在 MRO 訂單中首先找到,因此A不會抱怨它的存在。 我也用dataclass試過這個:

from abc import ABC, abstractmethod
from dataclasses import dataclass, field

class A(ABC):
    @property
    @abstractmethod
    def prop(self):
        pass

    def foo(self):
        print(self.prop())

@dataclass
class B:
    prop: int = field(default=5)

class C(B, A):
    pass

C()

但是,這不適用於attr

from abc import ABC, abstractmethod
import attr

@attr.s
class A(ABC):
    @property
    @abstractmethod
    def prop(self):
        pass

    def foo(self):
        print(self.prop())

@attr.s
class B:
    prop: int = attr.ib(default=5)

@attr.s
class C(B, A):
    pass

C()

運行它:

❯ python test.py                                                                                  
Traceback (most recent call last):
  File "test_mro_abstract_property.py", line 22, in <module>
    C()
TypeError: Can't instantiate abstract class C with abstract methods prop

我正在使用的代碼庫已經標准化了attr的使用,所以如果可能的話,我想繼續使用attr attrsdataclass有什么不同,以至於它無法發現prop成員? 這個問題有解決方法嗎?

我使用的 attr 版本是 22.1.0(最新版本)

有一種解決方法,但我不是 100% 為什么它有效:使 B 開槽:

@attr.s(slots=True)
class B:
    prop: int = attr.ib(default=5)

讓它工作。

我懷疑這是因為 abc 檢查__slots__並且它就在那里。

數據類將一些默認值作為 class 變量放在 class 主體上,但不是全部。

例如,這失敗了:

@dataclass
class B:
    prop: list = field(default_factory=list)

這種不一致是我不喜歡以特殊方式處理某些默認值的原因。


JFTR,在現代 attrs(2020 年 8 月的 20.1.0)中,您的代碼將如下所示(並且可以工作,因為默認情況下插槽處於打開狀態):

from abc import ABC, abstractmethod
import attr

@attr.define
class A(ABC):
    @property
    @abstractmethod
    def prop(self):
        pass

    def foo(self):
        print(self.prop())

@attr.define
class B:
    prop: int = attr.field(default=5)

@attr.define
class C(B, A):
    pass

C()

(如果您同意要求 21.3,您甚至可以使用import attrs

暫無
暫無

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

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