最终目标:让 isinstance(MyClass(), np.ndarray)
和 issubclass(MyClass, np.ndarray)
均返回 True
没有 MyClass
调用 np.ndarray.__new__()
。
假设我已经实现了 numpy.ndarray
的所有方法,并且我想对其进行设置,以便它能够通过 ndarray<的
,但我不希望它实际上从 isinstance
检查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__ 即可进行类型检查。所以我的类(class)是:
类 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 代码量是多少?也许我可以导入一个函数来实例化该类,而无需升级 mro?
最佳答案
我不知道是否可以伪造 isinstance
和 issubclass
,但在以下方法中,您可以定义传递给 np.ndarray 的类.__new__
仅您想要的参数:
import numpy as np
class BlockingClass(np.ndarray):
def __new__(cls, *args, **kwargs):
ndarray_kw = ['shape', 'dtype', 'buffer' 'offset', 'strides', 'order']
to_ndarray = {}
to_myclass = {}
for k,v in kwargs.items():
if k not in ndarray_kw:
to_myclass[k] = v
else:
to_ndarray[k] = v
new = np.ndarray.__new__(cls, *args, **to_ndarray)
for k,v in to_myclass.items():
setattr(new, k, v)
return new
def __init__(self, *args, **kwargs):
self.test = 1
self.args = args
self.kwargs = kwargs
关于python - 跳过 ndarray 子类中的 numpy __new__ (或者可能覆盖/定义 C 或 cython 中的类),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18284660/