我的numpy数组如何实现更简洁的__repr__输出?

3

当我展示一个数组时,ndarray对象的默认__repr__()方法对于我的需求来说太过冗长:

a = np.eye(32)
b = {'hello':42, 'array':a}
b

生成:

{'array': array([[ 1.,  0.,  0., ...,  0.,  0.,  0.],
       [ 0.,  1.,  0., ...,  0.,  0.,  0.],
       [ 0.,  0.,  1., ...,  0.,  0.,  0.],
   ..., 
       [ 0.,  0.,  0., ...,  1.,  0.,  0.],
       [ 0.,  0.,  0., ...,  0.,  1.,  0.],
       [ 0.,  0.,  0., ...,  0.,  0.,  1.]]), 'hello': 42}

我尝试了一个丑陋的解决方案,重新分配__repr__
def wow():
    return "wow!"

a.__repr__ = wow

这导致了一种归因错误,我并不感到惊讶:

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    a.__repr__ = wow
AttributeError: 'numpy.ndarray' object attribute '__repr__' is read-only

我可以创建一个包含自定义repr的类,这正是我想要的:

class NP(object):
    def __init__(self, a):
        self.a = a
    def __repr__(self):
        s0, s1 = self.a.shape
        dtp    = self.a.dtype
        return '{}x{} {}'.format(s0, s1, dtp)

A = NP(a)
A

现在会产生以下结果:

32x32 float64

但是问题在于现在我需要到处访问该属性。A.sum() 会失败,A.a.sum() 可以正常工作。

是否有一种直接使用 NumPy 解决这个问题的方法?


1
看起来你想要一个 ndarray 的子类,而不是组合。 - timgeb
@timgeb 听起来确实是我想做的事情。请看此评论 - uhoh
1个回答

7
使用np.set_string_function函数:
>>> def __repr__(self):
...     s0, s1 = self.shape                                                               
...     dtp    = self.dtype                                                                   
...     return '{}x{} {}'.format(s0, s1, dtp)                                                                   
...                                                                                                                 
>>> np.set_string_function(__repr__)                               
>>> np.identity(5)                                                 
5x5 float64                                                                                                         

如果您需要更高级的显示效果,可以查看reprlib

另一方面,如果您只想将其缩短一点,np.set_printoptions可能是最简单的选择。

如果您需要将此应用于数组的子集,则子类化确实是最佳选择。但我不确定numpy中子类化的当前状态。至少可以说,以前存在许多微妙之处。

>>> class myarray(np.ndarray):                                                                            
...    def __repr__(self):                                                                                
...        return "wow!"
...                                                                                                                 
>>> np.identity(5).view(myarray)                                                                                  
wow!                           

我明白了,这将适用于所有数组,对我来说肯定是一种改进。但我需要将其应用于一个数组,这就是为什么我尝试使用 a.__repr__ = wow 的原因。这能指向一个数组而不是所有数组吗? - uhoh
@uhoh 不直接可以,但子类化可能可行。请参见更新的答案。 - Paul Panzer
我明白你的意思...通过子类化ndarray,由于ndarray类的新实例可以通过三种不同的方式产生,这使得情况变得复杂。这些方式是...因此在这种情况下,set_string_function可能是最好的选择。谢谢! - uhoh
这对我有用!顺便说一下,我试图比使用print(arr)更轻松地获得矩阵表示,可以使用np.set_string_function(np.array2string)来完成。 - wjandrea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接