正在给自己的游戏补测试,需要 Mock,也没有方便的办法能让 mypy 接受我的 mock 对象,于是想了一个奇技淫巧:
class MockMeta(type):
def mro(cls):
bases = cls.__bases__
assert len(bases) == 1
return [cls, object]
class A(object):
def foo(self):
print('foo')
class C(A, metaclass=MockMeta):
def baz(self):
print('baz')
希望这样能让系统以为我的 C
是A
的 subclass 但是实际上不会有 A
的方法能够被 C
访问(希望 Mock 对象能过类型检查,同时不会不小心调用到实际的 A
上的代码)
然而……
In [7]: C()
Out[7]: <__main__.C at 0x7fe5d2ddfb00>
In [8]: C.mro()
Out[8]: [__main__.C, object]
In [9]: issubclass(C, A)
Out[9]: False
In [10]: issubclass(A, C)
Out[10]: False
In [11]: C.__bases__
Out[11]: (__main__.A,)
处于好奇看了下 CPython 的源码(题图),妈蛋居然就是找 MRO 的,找不到 MRO 才找 __bases__
。
应该看看 Abstract Base Class ?上班去了,晚上再折腾。
UPDATE
成功地骗过了 mypy,所以算是达成目标了