在ndarray子类中跳过numpy __new__(或者可能覆盖/定义C或cython中的类) [英] Skip numpy __new__ in ndarray subclass (or possibly overriding/defining classes in C or cython)

查看:154
本文介绍了在ndarray子类中跳过numpy __new__(或者可能覆盖/定义C或cython中的类)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

终极目标: isinstance(MyClass(),np.ndarray) issubclass(MyClass,np.ndarray)两个返回 True 而不 MyClass 调用 np.ndarray .__ new __()






我已经实现了所有的< c $ c> numpy.ndarray 并且我想设置它,以便它将通过 isinstance 检查 ndarray ,但我不要实际从 ndarray 调用 __ 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆