在ndarray子类中跳过numpy __new__(或者可能覆盖/定义C或cython中的类) [英] Skip numpy __new__ in ndarray subclass (or possibly overriding/defining classes in C or cython)
问题描述
终极目标: isinstance(MyClass(),np.ndarray)
和 issubclass(MyClass,np.ndarray)
两个返回 True
而不 MyClass
调用 np.ndarray .__ new __()
。
我已经实现了所有的< c $ c> numpy.ndarray 并且我想设置它,以便它将通过 isinstance
检查 ndarray
,但我不要实际从 ndarray $ c>调用
__ new __
$ c>。
最初,我在想这样的:
import numpy as np
class BlockingClass(np.ndarray):
def __new __(cls,* args,** kwargs):
return object .__ new __(cls)$ b $不幸的是,试图实例化 Dummy()
会产生这个错误关于它不安全: TypeError:object .__ new __(Dummy)不安全,使用numpy.ndarray .__ new __
如果它是一个子类对象的类,它会工作:
class BlockingClass2(object):
def __new __(cls,* args,** kwargs):
return object .__ new __(cls)
BlockingClass2()#没有错误
我确定这是因为 ndarray
是一个C类,所以我想在C类(或者,最好是一个Cython类)重写它,并使用多继承来获得typecheck工作,而不调用 __ new __
。所以我的类将是:
class MyClass(BlockingClass,np.ndarray):
pass
其中 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
b $ b
但是,当 BlockingClass
是使用定义 __ new __
仍然调用 __ new __
方法。如果我不能在Cython中做到这一点,那么我需要定义一个通过多重继承跳过 ndarray
' __ new __
?也许我可以导入一个函数来实例化类,而不需要上升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():
如果k不在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
Ultimate goal: have isinstance(MyClass(), np.ndarray)
and issubclass(MyClass, np.ndarray)
both return True
without MyClass
calling np.ndarray.__new__()
.
Let's say I've implemented all the methods of numpy.ndarray
and I want to set it up so that it will pass isinstance
checks for ndarray
, but I don't want it to actually call __new__
from ndarray
.
Initially, I was thinking of something like this:
import numpy as np
class BlockingClass(np.ndarray):
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
Unfortunately, trying to instantiate Dummy()
yields this error about it not being safe:
TypeError: object.__new__(Dummy) is not safe, use numpy.ndarray.__new__()
This works if it's a class that subclasses object:
class BlockingClass2(object):
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
BlockingClass2() # No error
I'm pretty sure that it's because ndarray
is a C class, so I was thinking of overriding it in a c-class (or, preferably, a Cython class) and using multiple inheritance to get the typecheck to work without calling __new__
. So my class would be:
class MyClass(BlockingClass, np.ndarray):
pass
where BlockingClass
would be the c-defined function. I'd really prefer to do this in Cython instead, but I can't figure out how to get it to work. I've tried doing:
cdef class BlockingClass:
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
but this generates the same 'unsafe' error as well as with __cinit__
.
cdef class BlockingClass:
def __cinit__(self, *args, **kwargs):
# do stuff
return self
But, when BlockingClass
is subclassed with multiple inheritance like above with an object that defines __new__
, that __new__
method is still called. If I can't do this in Cython, what's the minimal amount of C code I would need to define a baseclass that, through multiple inheritance, would skip ndarray
's __new__
? Maybe I can cimport a function to instantiate the class without going up the mro?
解决方案 I don't know if it is possible to fake isinstance
and issubclass
, but in the following approach you can define your class passing to np.ndarray.__new__
only the arguments that you want:
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
这篇关于在ndarray子类中跳过numpy __new__(或者可能覆盖/定义C或cython中的类)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!