python 除了同时使用类方法和属性装饰器之外,还有哪些类似的替代方案?

holgip5t  于 2023-06-04  发布在  Python
关注(0)|答案(2)|浏览(125)

除了同时使用类方法和属性装饰器之外,还有哪些类似的替代方案?
在python 3.11和更高版本中,不再支持组合它们:https://docs.python.org/3.11/library/functions.html#classmethod
我有这样的代码:

class Bike:
  @classmethod
  @property
  def tire_type(cls) -> tire_type.Road:
    return tire_type.Road

from . import tire_type

tire_type导入必须是最后一个,因为它对当前模块具有循环依赖性。在不合并两个装饰器的Bike类中提供轮胎属性有哪些选项?
我还希望tire_type类型提示在vscode中正确显示。

deyfvvtc

deyfvvtc1#

您可以始终实现自己的描述符。下面是一个最基本的方法,它假设你正在修饰的方法是一个“getter”:

>>> class classproperty:
...     def __init__(self, method):
...         self.method = method
...     def __get__(self, obj, cls=None):
...         if cls is None:
...             cls = type(obj)
...         return self.method(cls)
...
>>> class Foo:
...     bar = 42
...     @classproperty
...     def baz(cls):
...         return cls.bar * 2
...
>>> class FooSpecial(Foo):
...     bar = 11
...
>>> Foo.baz
84
>>> FooSpecial.baz
22

classmethodproperty都是作为描述符实现的。你可以阅读更多关于描述符协议如何工作的信息,in the Descriptor HowTo实际上展示了propertyclassmethod的纯python实现,如果你需要详细说明以上内容,你可以参考。

c6ubokkw

c6ubokkw2#

一些选项包括
1.编写自定义描述符,使用泛型返回 Package 的类型

T = typing.TypeVar('T')

class classprop(typing.Generic[T]):
    def __init__(self, method: typing.Callable[..., T]):
        self.method = method
        functools.update_wrapper(self, method) # type: ignore

    def __get__(self, obj, cls=None) -> T:
        if cls is None:
            cls = type(obj)
        return self.method(cls)

class Bike:
    @classprop
    def tire_type(cls) -> typing.Type[tire_type.Road]:
        return tire_type.Road

print(Bike.tire_type)

1.使方法仅为classmethod,这将保持类访问,但需要()
1.将其设置为静态方法,但需要()
1.使类成为数据类,并使用default_factory返回所需的类

@dataclasses.dataclass
class Bike
    tire_type: typing.Type[tire_type.Road] = dataclasses.field(
        default_factory=lambda: tire_type.Road
    )

print(Bike().tire_type)

选项1或4是首选的,因为它不需要(),并且它允许属性的类型描述,并且在访问Bike或示例化它时延迟属性的计算

相关问题