带有描述符的类型提示

问题描述 投票:0回答:3

这个拉取请求中,它看起来像是添加了对描述符的类型提示支持。

然而,看起来没有最终的“正确”用法示例被发布,也没有任何文档被添加到

typing
模块Mypy.

看起来正确的用法是这个

from typing import TypeVar

T = TypeVar('T')
V = TypeVar('V')


class classproperty():
    def __init__(self, getter: Callable[[Type[T]], V]) -> None:
        self.getter = getter

    def __get__(self, instance: Optional[T], owner: Type[T]) -> V:
        return self.getter(owner)


def forty_two(cls: Type) -> int:
    return 42


class C:
    forty_two: int = classproperty(forty_two)

这似乎合乎逻辑,但我不知道这是否真的是正确的做事方式。

有这方面的文件吗?或者实际适用于合并版本的完整示例?

python python-3.x type-hinting mypy python-descriptors
3个回答
3
投票

问题中描述的方法似乎适用于 Mypy 和 PyCharm 类型检查器。

编辑:显然我的示例代码类型检查,但 MyPy 实际上不能 infer 版本 0.800 的类型。

"""Defines the `classproperty` decorator."""

from typing import Any, Callable, Optional, Type, TypeVar


T = TypeVar("T")
V = TypeVar("V")


class classproperty(property):
    """Class property decorator."""

    def __init__(self, getter: Callable[[Any], V]) -> None:
        """Override getter."""
        self.getter = getter  # type: ignore

    def __get__(self, instance: Optional[T], owner: Type[T]) -> V:  # type: ignore
        return self.getter(owner)  # type: ignore

    def __set__(self, obj, value):
        super(classproperty, self).__set__(type(obj), value)

    def __delete__(self, obj):
        super(classproperty, self).__delete__(type(obj))


class Thing:
    @classproperty
    def value1(cls) -> int:
        return 44

    value2 = classproperty(lambda cls: 55)

    @property
    def value3(self) -> int:
        return 66


thing = Thing()
reveal_type(thing.value1)
reveal_type(thing.value2)
reveal_type(thing.value3)
main.py:40: note: Revealed type is '<nothing>'
main.py:41: note: Revealed type is '<nothing>'
main.py:42: note: Revealed type is 'builtins.int'

https://mypy-play.net/?mypy=0.800&python=3.9&gist=79f6fab466ecc4c4b45b75f1c7b6a6a8.


1
投票

我无法让示例与 MyPy 一起工作。但是,下面的派生定义对我有用:

"""Defines the `classproperty` decorator."""

from typing import Any, Callable, Optional, Type, TypeVar

T = TypeVar("T")
V = TypeVar("V")


class classproperty(property):
    """Class property decorator."""

    def __init__(self, getter: Callable[[Any], V]) -> None:
        """Override getter."""
        self.getter = getter  # type: ignore

    def __get__(self, instance: Optional[T], owner: Type[T]) -> V:  # type: ignore
        return self.getter(owner)  # type: ignore

    def __set__(self, obj, value):
        super(classproperty, self).__set__(type(obj), value)

    def __delete__(self, obj):
        super(classproperty, self).__delete__(type(obj))


0
投票

经过一段时间的努力解决这个问题,当你搜索“类型提示描述符”时,这个页面是最重要的结果,我想分享一个完全满足 mypy 和 pyright 静态类型检查器的解决方案,它与 python 3.6 兼容并且确实不继承

property

from typing import Callable, Generic, Type, TypeVar, overload, Union


Instance = TypeVar('Instance')
Value = TypeVar('Value')
Attribute = TypeVar('Attribute')


class Descriptor(Generic[Instance, Attribute, Value]):
    def __init__(self, method: Callable[[Instance, Attribute], Value]):
        """ Called on initialisation of descriptor """

    @overload
    def __get__(self, instance: None, owner: Type[Instance]) -> 'Descriptor':
        """ Called when an attribute is accessed via class not an instance """

    @overload
    def __get__(self, instance: Instance, owner: Type[Instance]) -> Value:
        """ Called when an attribute is accessed on an instance variable """

    def __get__(self, instance: Union[Instance, None], owner: Type[Instance]) -> Union[Value, 'Descriptor']:
        """ Full implementation is declared here """
        ...

    def __set__(self, instance: Instance, value: Value):
        """ Called when setting a value."""
        
© www.soinside.com 2019 - 2024. All rights reserved.