TypeError:“property”类型的对象没有 len()

TypeError: object of type 'property' has no len()

提问人:Itay Dvash 提问时间:5/8/2023 最后编辑:Itay Dvash 更新时间:5/8/2023 访问量:814

问:

我有一个包含自定义对象列表的类的代码。对于此列表,我创建了一个属性以允许访问它:_offersOffer

class OffersManager:    
    _offers: list[Offer] = []
    
    @property
    def offers(cls) -> list[Offer]:
        return cls._offers

问题是程序将此列表视为“属性”对象,因此当我尝试获取列表的长度时,它给了我一个错误:

>>> len(OffersManager.offers)
>>> Traceback (most recent call last):
      File "<pyshell#1>", line 1, in <module>
        len(OffersManager.offers)
    TypeError: object of type 'property' has no len()

有人可以告诉我使属性以列表形式返回属性的正确方法吗?

Python 对象 属性

评论

0赞 chepner 5/8/2023
您应该从 的实例进行访问,而不是从类本身进行访问。offersOffersManager

答:

2赞 yut23 5/8/2023 #1

从评论中更新:这已被弃用,可能无法正常工作,请改用 SUTerliakov 答案中的元类方法。


您需要将属性标记为类方法,以便它绑定到类本身而不是实例:

class OffersManager:    
    _offers: list[OfferData] = []
    
    @classmethod
    @property
    def offers(cls) -> list[OfferData]:
        return cls._offers

评论

0赞 Itay Dvash 5/8/2023
非常感谢!我会向那些将来会遇到这个问题的人强调,装饰器的顺序很重要(我试图反转它们并得到同样的错误)。
2赞 chepner 5/8/2023
不建议这样做;允许您定义“类”属性的机制已弃用;文档表明它已从 Python 3.11 中删除(尽管它似乎仍然可以在该版本中工作)。
0赞 yut23 5/8/2023
有趣的是,我不知道!为了将来参考,请参阅 Python 3.11 发行说明条目。
1赞 STerliakov 5/8/2023 #2

为了避免过去从未正常工作过的已弃用功能,可以在元类上定义属性:

from __future__ import annotations
from typing import TypeAlias

OfferData: TypeAlias = int


class OffersManagerMeta(type):
    _offers: list[OfferData] = []
    
    @property
    def offers(cls) -> list[OfferData]:
        return cls._offers


class OffersManager(metaclass=OffersManagerMeta):
    pass


print(OffersManager.offers)
OffersManager._offers = [1, 2]
print(OffersManager.offers)

这甚至通过了严格的.mypy

评论

0赞 Bartek Lachowicz 9/5/2023
真正的问题:为什么在 OffersManagerMeta 中使用 inherit from type?