numpy.ndarray:转换为“普通”类
[Python 3]
我喜欢用 ndarray
,但是用起来有点烦。
我遇到一个问题。我想写一个 class Array
,这个类能继承 ndarray
的很多功能,但它只能以一种方式创建:就是生成一个填满零的特定大小的数组。我本来想这样写:
class Array(numpy.ndarray):
def __init__(size):
# What do here?
我想用 super().__init__
来传一些参数,创建一个填满零的数组,但这行不通,因为 ndarray
是用一个全局函数 numpy.zeros
来创建填满零的数组,而不是用构造函数。
问题:
为什么在很多情况下,
ndarray
会使用全局(模块)函数,而不是构造函数?如果我想在面向对象的环境中重用它们,这就很麻烦。我需要的
class Array
最好怎么定义?我是不是应该手动把ndarray
填充为零,还是有其他方法可以重用zeros
函数?
3 个回答
ndarray的继承有点复杂。ndarray
甚至没有 __init(self, )___
这个方法,所以它不能被子类调用,但这样设计是有原因的。你可以查看numpy的文档,了解子类化的相关内容。
顺便问一下,你能具体说说你的需求吗?其实创建一个利用ndarray的类还是很简单的,但要创建一个继承自ndarray的子类,以便使用numpy的所有功能,那就复杂多了。
我似乎无法对自己的帖子评论,真奇怪
@Philipp:这个方法会被Python调用,但不会被numpy调用。创建ndarray的方式有三种,如何处理这三种情况的指导可以在那个文档中找到。
为什么ndarray在很多情况下使用全局(模块)函数而不是构造函数呢?
- 为了和Matlab兼容,像
zeros
或ones
这样的函数最初就是从那里来的。 - 全局工厂函数写起来快,理解起来也简单。构造函数应该有什么样的语义呢?比如,怎么用一个构造函数来表示简单的
zeros
、empty
或ones
呢?实际上,这种工厂函数在其他编程语言中也很常见。
我需要定义
class Array
,最好的方法是什么?
import numpy
class Array(numpy.ndarray):
def __new__(cls, size):
result = numpy.ndarray.__new__(Array, size)
result.fill(0)
return result
arr = Array(5)
def test(a):
print type(a), a
test(arr)
test(arr[2:4])
test(arr.view(int))
arr[2:4] = 5.5
test(arr)
test(arr[2:4])
test(arr.view(int))
注意这是Python 2,但只需要做一些小修改就能在Python 3中使用。
如果你不喜欢 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