Python numpy.ndarray:转换为“a”;“正常”;班

Python numpy.ndarray:转换为“a”;“正常”;班,python,numpy,python-3.x,wrapper,Python,Numpy,Python 3.x,Wrapper,[Python 3] 我喜欢ndarray,但我觉得用起来很烦人 我面临一个问题。我想编写类数组,它将继承ndarray的大部分功能,但只有一种实例化方法:作为特定大小的零填充数组。我希望写: class Array(numpy.ndarray): def __init__(size): # What do here? 我想用一些参数调用super()。\uuuu init\uuu来创建一个零填充数组,但它不起作用,因为ndarray使用一个全局函数numpy.zeros(而不是构

[Python 3]

我喜欢
ndarray
,但我觉得用起来很烦人

我面临一个问题。我想编写
类数组
,它将继承ndarray的大部分功能,但只有一种实例化方法:作为特定大小的零填充数组。我希望写:

class Array(numpy.ndarray):
  def __init__(size):
    # What do here?
我想用一些参数调用
super()。\uuuu init\uuu
来创建一个零填充数组,但它不起作用,因为
ndarray
使用一个全局函数
numpy.zeros
(而不是构造函数)来创建一个零填充数组

问题:

  • 为什么ndarray在许多情况下使用全局(模块)函数而不是构造函数?如果我试图在面向对象的环境中重用它们,这是一个很大的麻烦

  • 定义我需要的
    类数组
    的最佳方法是什么?我应该用零手动填充
    ndarray
    ,还是有办法重用
    zeros
    函数

  • 为什么ndarray在许多情况下使用全局(模块)函数而不是构造函数

  • 与Matlab兼容/类似,Matlab的函数如
    zero
    ones
    最初来自Matlab
  • 全局工厂函数编写速度快,易于理解。构造器的语义应该是什么,例如,你如何用一个构造器来表达一个简单的
    ?事实上,这种工厂函数在其他编程语言中也很常见
  • 定义我需要的
    类数组
    的最佳方法是什么


    请注意,这是Python2,但使用Python3只需稍作修改。

    如果您不喜欢
    ndarray
    接口,则不要继承它。您可以定义自己的接口,并将其余接口委托给ndarray和numpy

    import functools
    import numpy as np
    
    
    class Array(object):
    
        def __init__(self, size):
            self._array = np.zeros(size)
    
        def __getattr__(self, attr):
            try: return getattr(self._array, attr)
            except AttributeError:
                # extend interface to all functions from numpy
                f = getattr(np, attr, None)
                if hasattr(f, '__call__'):
                    return functools.partial(f, self._array)
                else:
                    raise AttributeError(attr)
    
        def allzero(self):
            return np.allclose(self._array, 0)
    
    
    a = Array(10)
    # ndarray doesn't have 'sometrue()' that is the same as 'any()' that it has.
    assert a.sometrue() == a.any() == False
    assert a.allzero()
    
    try: a.non_existent
    except AttributeError:
        pass
    else:
        assert 0
    

    ndarray的继承有点棘手
    ndarray
    甚至没有方法
    \uuuu init(self,)\uuuuu
    ,因此无法从子类调用它,但这是有原因的。请参阅的numpy文档

    顺便问一下,你能更具体地说明你的特殊需要吗?根据您自己的需要编写一个类(使用ndarray)仍然很容易,但是ndarray的一个子类通过所有numpy机制是完全不同的问题

    似乎我不能评论我自己的帖子,奇怪的

    @Philipp:它将由Python调用,但不会由numpy调用。实例化ndarray有三种方法,该文档中给出了如何处理所有情况的指导原则。

    我不明白您为什么要创建自己的类。与
    numpy.zeros()
    工厂函数相比,它有什么优势?如果你不喜欢这个名字,就把它重命名,比如
    create\u array=numpy.zeros
    。我不再确定它有什么优势。也许我只是不习惯工厂的功能。我必须考虑一下。@Sven Marnach:我找到了几个关于这个一般主题的链接:没有特定于Python的内容,但是其他语言的一般评论似乎适用。就我所知,工厂的功能并没有什么坏处(除了我个人的喜好)。
    ndarray
    构造函数的
    shape
    参数可能只是一个整数而不是元组。2. <默认值为code>dtype=float。3.在Python 3中,在本例中可以省略
    super()
    的参数。结合这些注释,构造函数的前两行缩减为
    super()。(构造函数签名通常没有文档记录。)@Philipp:它记录在类的docstring中,而不是构造函数本身。但这实际上是文档所属的地方。@Sven:我的意思是,文档说
    shape
    必须是一个元组,而不是说
    dtype
    默认为
    float
    。我好像错过了这个文档。但是为什么在我的示例中调用
    \uuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。你说得对,对ndarray子类化太难了。我将在@J.F.Sebastian中采用容器方法。非常简洁。我假设所有
    numpy
    全局函数在使用
    ndarray
    参数调用时与
    ndarray
    的同名实例方法具有相同的语义。要更改为Python 3,我只需从类定义中删除
    (对象)
    ,对吗?[并不是说离开它会导致问题。]@max:代码在2.x和Python3上都可以正常工作,没有任何更改。我似乎遗漏了一些东西。您不从
    ndarray
    派生,但如果请求了任何属性,则首先尝试从
    ndarray
    实例获取属性。首先,从
    ndarray
    派生不是更容易吗?您仍然可以添加魔法,将numpy中的模块级函数添加为方法,但我认为这也不是一个好主意,因为它们中的大多数已经是方法了,其余的作为方法没有意义(只有极少数例外)。@Sven Marnach:前提是OP发现
    ndarray
    使用起来很烦人。委派是一种比继承更灵活的更改类接口的方法。代码不是最终的解决方案,但它只是一个框架示例,允许扩展它以使用黑名单、白名单等方法。我同意模块级函数。代码显示了如何做到这一点;它并不主张这样做是明智的。
    import functools
    import numpy as np
    
    
    class Array(object):
    
        def __init__(self, size):
            self._array = np.zeros(size)
    
        def __getattr__(self, attr):
            try: return getattr(self._array, attr)
            except AttributeError:
                # extend interface to all functions from numpy
                f = getattr(np, attr, None)
                if hasattr(f, '__call__'):
                    return functools.partial(f, self._array)
                else:
                    raise AttributeError(attr)
    
        def allzero(self):
            return np.allclose(self._array, 0)
    
    
    a = Array(10)
    # ndarray doesn't have 'sometrue()' that is the same as 'any()' that it has.
    assert a.sometrue() == a.any() == False
    assert a.allzero()
    
    try: a.non_existent
    except AttributeError:
        pass
    else:
        assert 0