如何在子类上“取消定义”Python魔术方法?

时间:2017-02-20 10:38:10

标签: python python-3.x operator-overloading liskov-substitution-principle python-datamodel

Python 3中是否有一种方法可以指示某个类不支持其父类支持的某些操作?*我知道类可以将__hash__设置为None以指示类型是不可删除的,但这似乎不起作用。

例如,假设我有一个带有__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。 ;)

1 个答案:

答案 0 :(得分:2)

我不会期待&#34;取消定义&#34;因为那可能会让它更加混乱。我是明确的,并为其量身定制TypeError消息,说明为什么此集合不支持__len__

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