Как я могу отменить определение магических методов Python в подклассе?

Есть ли способ в Python 3 указать, что класс не поддерживает какую-либо операцию, которую поддерживает его родительский класс? .

Например, предположим, что у меня есть некоторый класс коллекции с методом __len__, и я хочу создать дочерний класс, представляющий неограниченную коллекцию, размер которой не определен. Если я устанавливаю __len__ в None в подклассе, я получаю уродливое/запутанное сообщение об ошибке, когда пытаюсь получить длину коллекции.

>>> class C:
...     def __len__(self):
...         return 3
... 
>>> class D(C):
...     __len__ = None
... 
>>> len(D())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable

Я хотел бы получить ошибку, как если бы D вообще не определял __len__:

>>> class E:
...     pass
...
>>> len(E())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'E' has no len()

Этот вопрос связан, однако мой вопрос относится конкретно к магическим методам/перегрузке операторов. Поскольку магические методы Python ищутся непосредственно в типе объекта, некоторые возможные подходы, такие как переопределение __getattribute__ или использование дескрипторов, здесь не сработают.

*Примечание. Я знаю, что это нарушило бы принцип подстановки Лисков, но если мне нужна безопасность типов, я не будет использовать Python в первую очередь. ;)


comment
Почему не raise NotImplementedError от ребенка? Также обратите внимание, что динамическая типизация — это не то же самое, что создание сломанной структуры класса; не могли бы вы дать некоторый контекст относительно того, почему вы думаете, что вам это нужно?   -  person jonrsharpe    schedule 20.02.2017


Ответы (1)


Я бы не стал «не определять» его, так как это может сделать его более запутанным. Я был бы явным и приспособил к нему сообщение TypeError, в котором указано, почему эта коллекция не поддерживает __len__ :

class D(C):
    def __len__(self):
        raise TypeError("Unbounded collection defines no __len__")
person Dimitris Fasarakis Hilliard    schedule 20.02.2017