如何使用 mypy 和 @属性 赋值?

How can I assign values with mypy and @property?

我正在使用 @属性 装饰器并为它赋值 属性。但是,mypy 对我的代码(有效)抛出错误。我做错了什么吗?我怎样才能修复我的代码以使 mypy 不抱怨?

MVCE

# Core Library
from abc import ABCMeta, abstractmethod


class ListNode(metaclass=ABCMeta):
    def __init__(self, value):
        """Every list node should have a value at initialization."""

    @property
    @abstractmethod
    def value(self):
        """Read the value attribute"""

    @abstractmethod
    def next(self):
        """Read the next attribute"""


class SinglyLinkedListNode(ListNode):
    def __init__(self, value):
        self.value = value
        self.next = None  # Optional[SinglyLinkedListNode]

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        self._value = value

    @property
    def next(self):
        return self._next

    @next.setter
    def next(self, next_):
        self._next = next_


def reverse(list_node: ListNode) -> ListNode:
    """Reverse a list."""
    current = list_node
    previous = None

    while current is not None:
        previous, current.next, current = current, previous, current.next  # This throws the error

    return previous

错误:

mpu/datastructures/lists.py:47: error: Cannot assign to a method
mpu/datastructures/lists.py:47: error: Incompatible types in assignment (expression has type "ListNode", variable has type "Callable[[], Any]")
mpu/datastructures/lists.py:47: error: Incompatible types in assignment (expression has type "Callable[[], Any]", variable has type "ListNode")

在你的例子中可能有错字,而不是

self.next = None

应该是

self._next = None

因为我们正在用字段覆盖 property 您的代码似乎可以工作,但可能不是它的预期方式。

而且ListNode.next好像也是property太像了

class ListNode(metaclass=ABCMeta):
    ...

    @property
    @abstractmethod
    def next(self):
        """Read the next attribute"""

最后为 ListNode.next

添加 setter
    @next.setter
    def next(self, next_):
        """Write the next attribute"""

使错误消失。


顺便说一句,用 abstractmethod 装饰 ListNode.next setter 会导致错误

> mypy test.py
test.py:14: error: Overloaded method has both abstract and non-abstract variants
test.py:19: error: Decorated property not supported
test.py:53: error: Property "next" defined in "ListNode" is read-only

并且似乎是多余的,因为为 SinglyLinkedListNode.next 删除 setter 会导致

> mypy test.py
test.py:37: error: Read-only property cannot override read-write property

为了让 type comment 正常工作,我们需要添加 type: 前缀

class SinglyLinkedListNode(ListNode):
    def __init__(self, value):
        self.value = value
        self._next = None  # type: Optional[SinglyLinkedListNode]

(我们还可以添加from typing import Optional,因为PyCharm不满意说“未解决的引用'Optional'”,但似乎对 mypy 没问题)。