Ошибка Pylint при наследовании из List [тип] - PullRequest
0 голосов
/ 23 апреля 2020

Я написал следующий фрагмент кода:

from typing import List

class Foo():
    def __init__(self, _a : int, _b : bool):
        self.a = _a
        self.b = _b

class Bar(List[Foo]):
    def print(self):
        for entry in self: # Non-iterable value self is used in an iterating contextpylint(not-an-iterable)
            print(entry.a)
            print(entry.b)

foo0 = Foo(0, True)
foo1 = Foo(1, False)
foo2 = Foo(2, True)
foo3 = Foo(3, False)
bar = Bar()
bar.append(foo0) # Instance of 'Bar' has no 'append' memberpylint(no-member)
bar.append(foo1) # Instance of 'Bar' has no 'append' memberpylint(no-member)
bar.append(foo2) # Instance of 'Bar' has no 'append' memberpylint(no-member)
bar.append(foo3) # Instance of 'Bar' has no 'append' memberpylint(no-member)

bar.print()

Он работает просто отлично и, кажется, делает то, что должен, но Pylint действительно не нравится (сообщения об ошибках в комментариях ).

Есть ли способ сделать эту остановку?

Ответы [ 2 ]

0 голосов
/ 02 мая 2020

Как отмечали другие в комментариях, List[Foo] - это не тип list, а подсказка типа , которую будут проверять определенные типы (например, mypy) использовать для анализа вашего кода. Правильное использование подсказок типа таково:

a: List[int] = [1, 2, 3]  # a is a list of ints
b: List[float] = []
b.append(1.0)
b.append("string")  # a type checker would point out that this is an error

С другой стороны, наследование встроенного типа list, вероятно, не даст вам желаемых результатов. По крайней мере, в CPython встроенные типы, такие как list и dict, имеют большинство методов, реализованных в C по соображениям производительности, поэтому невозможно напрямую переопределить определенные поведения. Прочитайте эту статью для получения более подробной информации.

Однако Python предоставляет класс UserList, который поддерживает наследование. Он в основном реализует поведение list в чистом Python, поэтому имеет худшую производительность, но более настраиваемый. Чтобы разрешить добавление в список объектов только определенных типов, вы можете просто переопределить метод appendextend и __iadd__ (+=), если хотите завершить) и вручную выполните проверку типа:

from collections import UserList

class Bar(UserList):
    def append(self, item):
        if not isinstance(item, Foo):
            raise ValueError
        super().append(item)

    def extend(self, items):
        if any(not isinstance(x, Foo) for x in items):
            raise ValueError
        super().extend(items)

    def __iadd__(self, items):
        self.extend(items)
        return self

    def print(self):
        for entry in self:
            print(entry.a)
            print(entry.b)

Вы можете проверить это при запуске следующего кода:

foo0 = Foo(0, True)
foo1 = Foo(1, False)
foo2 = Foo(2, True)
foo3 = Foo(3, False)
bar = Bar()
bar.append(foo0)
bar.extend([foo1])
bar += [foo2, foo3]

# Check that exceptions are correctly raised.
try:
    bar.append(None)
except ValueError:
    pass
else:
    print("Exception not raised")
try:
    bar += [foo0, foo1, None]
except ValueError:
    pass
else:
    print("Exception not raised")

bar.print()

Мы получим:

0
True
1
False
2
True
3
False
0 голосов
/ 23 апреля 2020

Это исправит все ошибки Pylint

from typing import List
class Foo():
    def __init__(self, _a : int, _b : bool):
        self.a = _a
        self.b = _b

class Bar(List[Foo]):
    def print(self):
        for entry in list(self):
            print(entry.a)
            print(entry.b)

foo0 = Foo(0, True)
foo1 = Foo(1, False)
foo2 = Foo(2, True)
foo3 = Foo(3, False)

bar = Bar([foo0,foo1,foo2,foo3])
bar.print()
...