Как отмечали другие в комментариях, 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, поэтому имеет худшую производительность, но более настраиваемый. Чтобы разрешить добавление в список объектов только определенных типов, вы можете просто переопределить метод append
(и extend
и __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