Nea*_*roo 1 python metaclass magic-methods isinstance python-3.x
我试图使我的类作为另一个对象出现,以规避正在使用的程序包中的惰性类型检查。更具体地说,我试图使我的对象作为另一个对象的实例出现(tuple在我的情况下),而实际上它甚至不是该对象的派生。
为了实现这一目标,我计划重写该__isinstance__方法,根据docs,该方法应该完全按照我的意愿进行。但是,由于我的尝试未成功,因此我似乎不知道该怎么做。
这是一个SSCCE,应该在所有情况下都可以isinstance回报False,但不能回报。
class FalseInstance(type):
def __instancecheck__(self, instance):
return False
class Foo(metaclass=FalseInstance):
pass
g = Foo()
isinstance(g, Foo)
> True
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
除了__metaclass__精确类型匹配的问题和快速路径之外,它的__instancecheck__工作方向与您尝试做的相反。类__instancecheck__检查其他对象是否被视为该类的虚拟实例,而不是该类的实例是否被视为其他类的虚拟实例。
如果你希望你的对象在isinstance检查中谎报它们的类型(你真的不应该),那么这样做的方法是谎报__class__,而不是实现__instancecheck__。
class BadIdea(object):
@property
def __class__(self):
return tuple
print(isinstance(BadIdea(), tuple)) # prints True
Run Code Online (Sandbox Code Playgroud)
顺便说一句,如果您想获取对象的实际类型,请使用type而不是检查__class__或isinstance。
如果在内部添加打印,FalseInstance.__instancecheck__您将看到甚至没有调用它。但是,如果您致电,isinstance('str', Foo)您将看到FalseInstance.__instancecheck__确实被调用。
这是由于在最优化isinstance的实现,立即返回True,如果type(obj) == given_class:
int
PyObject_IsInstance(PyObject *inst, PyObject *cls)
{
_Py_IDENTIFIER(__instancecheck__);
PyObject *checker;
/* Quick test for an exact match */
if (Py_TYPE(inst) == (PyTypeObject *)cls)
return 1;
.
.
.
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
367 次 |
| 最近记录: |