【发布时间】:2013-08-17 02:54:33
【问题描述】:
最终目标:让isinstance(MyClass(), np.ndarray) 和issubclass(MyClass, np.ndarray) 都返回True 而不 MyClass 调用np.ndarray.__new__()。
假设我已经实现了 numpy.ndarray 的所有方法,并且我想对其进行设置,以便通过 isinstance 检查 ndarray,但我不想要它实际上是从ndarray 调用__new__。
最初,我在想这样的事情:
import numpy as np
class BlockingClass(np.ndarray):
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
不幸的是,尝试实例化 Dummy() 会产生此错误,表明它不安全:
TypeError: object.__new__(Dummy) is not safe, use numpy.ndarray.__new__()
如果它是一个子类对象的类,则此方法有效:
class BlockingClass2(object):
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
BlockingClass2() # No error
我很确定这是因为 ndarray 是一个 C 类,所以我正在考虑在 c 类(或者,最好是 Cython 类)中覆盖它并使用多重继承来使类型检查工作无需致电__new__。所以我的课是:
类 MyClass(BlockingClass, np.ndarray): 通过
BlockingClass 是 c 定义的函数。我真的更喜欢在 Cython 中执行此操作,但我不知道如何让它工作。我试过这样做:
cdef class BlockingClass:
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
但这会产生与__cinit__ 相同的“不安全”错误。
cdef class BlockingClass:
def __cinit__(self, *args, **kwargs):
# do stuff
return self
但是,当BlockingClass 像上面那样使用定义__new__ 的对象通过多重继承进行子类化时,仍会调用__new__ 方法。如果我不能在 Cython 中执行此操作,我需要定义一个通过多重继承跳过 ndarray 的 __new__ 的基类的最少 C 代码量是多少?也许我可以 cimport 一个函数来实例化类而不用上 mro?
【问题讨论】:
-
我仍然很不清楚你为什么认为你需要这样做......如果它有一个ndarray的所有方法,你为什么需要检查类型?而且,无论您尝试做什么,您尝试从
__new__返回不同类型的代码肯定不会像 ndarray 一样,因为永远不会调用__init__。 -
@mgilson 向后兼容。该类以前是 ndarray 的子类,现在不需要了,客户端代码仍然可以通过检查它是否是 ndarray 的子类来检查对象。这很奇怪,因为您可以覆盖
__init__而不将其传递给 super,但是没有办法覆盖__new__而不将其传递给 mro...
标签: python class numpy subclass cython