0

Есть ли способ в Python 3 указать, что класс не поддерживает какую-либо операцию, поддерживаемую родительским классом? * Я знаю, что классы могут устанавливать __hash__ на None, чтобы указать, что тип не сотрясается, но это, похоже, не работает в целом.Как я могу «разгадать» магические методы Python в подклассе?

Например, предположим, что у меня есть некоторый класс коллекции с методом __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() 

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

* Примечание: Я знаю, что это нарушит Liskov substitution principle, но если бы я хотел, чтобы тип безопасности, я бы не использовал Python в первую очередь. ;)

+0

Почему бы не поднять 'NotImplementedError' от ребенка? Также обратите внимание, что динамическое типирование не то же самое, что создание разбитой структуры класса; не могли бы вы дать некоторый контекст относительно того, почему вы думаете, что вам нужно это? – jonrsharpe

ответ

2

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

class D(C): 
    def __len__(self): 
     raise TypeError("Unbounded collection defines no __len__")