Как я могу присвоить значения с помощью mypy и @property? - PullRequest
1 голос
/ 27 марта 2020

Я использую декоратор @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")

1 Ответ

1 голос
/ 04 апреля 2020

В вашем примере, вероятно, есть опечатка, вместо

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

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

делает ошибки исчезать.


Кстати, украшение ListNode.next сеттера с abstractmethod вызывает ошибки

> 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 вызывает

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

Также для комментария типа для работы нам нужно добавить type: префикс

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

(мы также можем добавить from typing import Optional, потому что PyCharm не удовлетворен, говоря « Неразрешенная ссылка« Необязательно »», но для mypy это нормально).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...