yaml.dump在Python中对象的numpy.array-type属性上抛出错误

yaml.dump在Python中对象的numpy.array-type属性上抛出错误,python,arrays,python-3.x,numpy,yaml,Python,Arrays,Python 3.x,Numpy,Yaml,我希望我的对象能够紧凑地打印出来(不需要加载),这样就可以将numpy.array打印为常规元组(在本例中)。相反,我看到一条错误消息TypeError:data-type-not-understanding 知道是什么导致错误消息,以及(一旦解决)如何 所需的输出类似于: object:A a_array: - 1, 2, 3 有什么想法吗 更新:这可能会起作用(如果可以实现):是否有一种方法可以让yaml representer将任何数组变量x替换为其x.tolist()表示?在对象中表

我希望我的对象能够紧凑地打印出来(不需要加载),这样就可以将numpy.array打印为常规元组(在本例中)。相反,我看到一条错误消息
TypeError:data-type-not-understanding

知道是什么导致错误消息,以及(一旦解决)如何

所需的输出类似于:

object:A
a_array: 
- 1, 2, 3
有什么想法吗


更新:这可能会起作用(如果可以实现):是否有一种方法可以让yaml representer将任何
数组
变量
x
替换为其
x.tolist()
表示?

在对象中表示时,可以将numpy数组封送到列表中。然后在从对象检索时取消对其进行编组:

class A:
    def __init__(self):
        from numpy import array
        self.a_lst = [1,2,3]

    def __repr__(self):
        from yaml import dump
        return dump(self, default_flow_style=False)

    # convert internal list to numpy array before returning.
    @property
    def my_arr(self):
        return array(self.a_lst)

    # convert array to list before storing internally.
    @my_arr.setter
    def my_arr(self, array):
        self.a_lst = array.tolist()

print(repr(A()))
关键是要确保在对象内部以普通python列表的形式存储数组,以便确保可以进行yaml转储


一个可能更好的替代方法是使用numpy提供的内置
dump
功能。请参阅。

在表示对象时,可以将numpy数组封送到列表中。然后在从对象检索时取消对其进行编组:

class A:
    def __init__(self):
        from numpy import array
        self.a_lst = [1,2,3]

    def __repr__(self):
        from yaml import dump
        return dump(self, default_flow_style=False)

    # convert internal list to numpy array before returning.
    @property
    def my_arr(self):
        return array(self.a_lst)

    # convert array to list before storing internally.
    @my_arr.setter
    def my_arr(self, array):
        self.a_lst = array.tolist()

print(repr(A()))
关键是要确保在对象内部以普通python列表的形式存储数组,以便确保可以进行yaml转储


一个可能更好的替代方法是使用numpy提供的内置
dump
功能。请参阅。

您是否有兴趣生成有效的
yaml
,或者仅使用
yaml
作为显示对象的方式?像“不需要加载”这样的短语暗示了后者

但是为什么要关注yaml呢?它是否以您想要的方式处理列表或序列

如果我使用
tolist
将数组转换为
yaml
可以转储的列表,我会得到:

In [130]: a = np.arange(3)
In [131]: print(yaml.dump({'a':a.tolist()},default_flow_style=False))
a:
- 0
- 1
- 2

In [132]: print(yaml.dump({'a':a.tolist()},default_flow_style=True))
{a: [0, 1, 2]}
我可以把字典的部分删掉。但无论如何,列表部分都不会显示为:

- 1, 2, 3
我看不出
yaml.dump
比默认数组显示有什么改进:

In [133]: print(a)
[0 1 2]
In [134]: print(repr(a))
array([0, 1, 2])
对于二维阵列(以及可以转换为二维的阵列),
np.savetxt
提供了一个紧凑的显示,使用
fmt
选项控制细节:

In [139]: np.savetxt('test',a[None,:], fmt='%d')
In [140]: cat 'test'
0 1 2
在这里,我实际上是在写入一个文件,并用system
cat
显示该文件,但我也可以写入字符串缓冲区

但我可以做得更好
savetxt
只需将数组一次写入一行到文件中。我可以直接使用相同的格式样式

我创建了一个
fmt
字符串,为
a
中的每个项目指定了
%
(这里是一个1d数组)。然后
fmt%tuple(…)
格式化它。这只是简单的Python字符串格式

In [144]: fmt = ', '.join(['%d']*a.shape[0])
In [145]: fmt
Out[145]: '%d, %d, %d'
In [146]: fmt%tuple(a.tolist())
Out[146]: '0, 1, 2'
我可以在格式中添加
-
和缩进、冒号等

In [144]: fmt = ', '.join(['%d']*a.shape[0])
In [145]: fmt
Out[145]: '%d, %d, %d'
In [146]: fmt%tuple(a.tolist())
Out[146]: '0, 1, 2'
================================

import numpy as np

class A:
    def __init__(self, anArray):
        self.a_array = anArray

    def __repr__(self):
        astr = ['object: %s'%self.__class__]
        astr.append('a_array:')
        astr.append(self.repr_array())
        return '\n'.join(astr)

    def repr_array(self):
        a = self.a_array
        if a.ndim==1:
            a = a[None,:]
        fmt = ', '.join(['%d']*a.shape[1])
        fmt = '- '+fmt
        astr = []
        for row in a:
             astr.append(fmt%tuple(row))
        astr = '\n'.join(astr)
        return astr

print A(np.arange(3))

print A(np.ones((3,2)))
import yaml
def numpy_representer_str(dumper, data):
    # first cut ndarray yaml representer
    astr = ', '.join(['%s']*data.shape[0])%tuple(data)
    return dumper.represent_scalar('!ndarray:', astr)

def numpy_representer_seq(dumper, data):
    return dumper.represent_sequence('!ndarray:', data.tolist())

yaml.add_representer(np.ndarray, numpy_representer_str)
print (yaml.dump({'a':np.arange(4)},default_flow_style=False))

yaml.add_representer(np.ndarray, numpy_representer_seq)
print (yaml.dump({'a':np.arange(4)},default_flow_style=False))

class A:
    def __init__(self, anArray):
        self.a_array = anArray

    def __repr__(self):
        astr = ['object: %s'%self.__class__]
        astr.append('a_array:')
        astr.append(self.repr_array())
        return '\n'.join(astr)

    def repr_array(self):
        return yaml.dump(self.a_array)
print (A(np.arange(3)))
print (A(np.arange(6).reshape(2,3)))
产生

object: __main__.A
a_array:
- 0, 1, 2
对于一维阵列,以及

object: __main__.A
a_array:
- 1, 1
- 1, 1
- 1, 1
对于二维阵列

=======================================

import numpy as np

class A:
    def __init__(self, anArray):
        self.a_array = anArray

    def __repr__(self):
        astr = ['object: %s'%self.__class__]
        astr.append('a_array:')
        astr.append(self.repr_array())
        return '\n'.join(astr)

    def repr_array(self):
        a = self.a_array
        if a.ndim==1:
            a = a[None,:]
        fmt = ', '.join(['%d']*a.shape[1])
        fmt = '- '+fmt
        astr = []
        for row in a:
             astr.append(fmt%tuple(row))
        astr = '\n'.join(astr)
        return astr

print A(np.arange(3))

print A(np.ones((3,2)))
import yaml
def numpy_representer_str(dumper, data):
    # first cut ndarray yaml representer
    astr = ', '.join(['%s']*data.shape[0])%tuple(data)
    return dumper.represent_scalar('!ndarray:', astr)

def numpy_representer_seq(dumper, data):
    return dumper.represent_sequence('!ndarray:', data.tolist())

yaml.add_representer(np.ndarray, numpy_representer_str)
print (yaml.dump({'a':np.arange(4)},default_flow_style=False))

yaml.add_representer(np.ndarray, numpy_representer_seq)
print (yaml.dump({'a':np.arange(4)},default_flow_style=False))

class A:
    def __init__(self, anArray):
        self.a_array = anArray

    def __repr__(self):
        astr = ['object: %s'%self.__class__]
        astr.append('a_array:')
        astr.append(self.repr_array())
        return '\n'.join(astr)

    def repr_array(self):
        return yaml.dump(self.a_array)
print (A(np.arange(3)))
print (A(np.arange(6).reshape(2,3)))
使用不同风格的numpy representer,我可以得到如下打印效果:

a: !ndarray: '0, 1, 2, 3'   # the string version

a: !ndarray:         # the sequence version
- 0
- 1
- 2
- 3

object: <class '__main__.A'>     # sequence version with 1d
a_array:
!ndarray: [0, 1, 2]

object: <class '__main__.A'>    # sequence version with 2d
a_array:
!ndarray:
- [0, 1, 2]
- [3, 4, 5]
a:!ndarray:'0,1,2,3'#字符串版本
a:!ndarray:#序列版本
- 0
- 1
- 2
- 3
对象:#具有1d的序列版本
一个数组:
!ndarray:[0,1,2]
对象:#具有2d的序列版本
一个数组:
!恩达拉:
- [0, 1, 2]
- [3, 4, 5]

您对生成有效的
yaml
感兴趣,还是仅仅使用
yaml
作为显示对象的方式?像“不需要加载”这样的短语暗示了后者

但是为什么要关注yaml呢?它是否以您想要的方式处理列表或序列

如果我使用
tolist
将数组转换为
yaml
可以转储的列表,我会得到:

In [130]: a = np.arange(3)
In [131]: print(yaml.dump({'a':a.tolist()},default_flow_style=False))
a:
- 0
- 1
- 2

In [132]: print(yaml.dump({'a':a.tolist()},default_flow_style=True))
{a: [0, 1, 2]}
我可以把字典的部分删掉。但无论如何,列表部分都不会显示为:

- 1, 2, 3
我看不出
yaml.dump
比默认数组显示有什么改进:

In [133]: print(a)
[0 1 2]
In [134]: print(repr(a))
array([0, 1, 2])
对于二维阵列(以及可以转换为二维的阵列),
np.savetxt
提供了一个紧凑的显示,使用
fmt
选项控制细节:

In [139]: np.savetxt('test',a[None,:], fmt='%d')
In [140]: cat 'test'
0 1 2
在这里,我实际上是在写入一个文件,并用system
cat
显示该文件,但我也可以写入字符串缓冲区

但我可以做得更好
savetxt
只需将数组一次写入一行到文件中。我可以直接使用相同的格式样式

我创建了一个
fmt
字符串,为
a
中的每个项目指定了
%
(这里是一个1d数组)。然后
fmt%tuple(…)
格式化它。这只是简单的Python字符串格式

In [144]: fmt = ', '.join(['%d']*a.shape[0])
In [145]: fmt
Out[145]: '%d, %d, %d'
In [146]: fmt%tuple(a.tolist())
Out[146]: '0, 1, 2'
我可以在格式中添加
-
和缩进、冒号等

In [144]: fmt = ', '.join(['%d']*a.shape[0])
In [145]: fmt
Out[145]: '%d, %d, %d'
In [146]: fmt%tuple(a.tolist())
Out[146]: '0, 1, 2'
================================

import numpy as np

class A:
    def __init__(self, anArray):
        self.a_array = anArray

    def __repr__(self):
        astr = ['object: %s'%self.__class__]
        astr.append('a_array:')
        astr.append(self.repr_array())
        return '\n'.join(astr)

    def repr_array(self):
        a = self.a_array
        if a.ndim==1:
            a = a[None,:]
        fmt = ', '.join(['%d']*a.shape[1])
        fmt = '- '+fmt
        astr = []
        for row in a:
             astr.append(fmt%tuple(row))
        astr = '\n'.join(astr)
        return astr

print A(np.arange(3))

print A(np.ones((3,2)))
import yaml
def numpy_representer_str(dumper, data):
    # first cut ndarray yaml representer
    astr = ', '.join(['%s']*data.shape[0])%tuple(data)
    return dumper.represent_scalar('!ndarray:', astr)

def numpy_representer_seq(dumper, data):
    return dumper.represent_sequence('!ndarray:', data.tolist())

yaml.add_representer(np.ndarray, numpy_representer_str)
print (yaml.dump({'a':np.arange(4)},default_flow_style=False))

yaml.add_representer(np.ndarray, numpy_representer_seq)
print (yaml.dump({'a':np.arange(4)},default_flow_style=False))

class A:
    def __init__(self, anArray):
        self.a_array = anArray

    def __repr__(self):
        astr = ['object: %s'%self.__class__]
        astr.append('a_array:')
        astr.append(self.repr_array())
        return '\n'.join(astr)

    def repr_array(self):
        return yaml.dump(self.a_array)
print (A(np.arange(3)))
print (A(np.arange(6).reshape(2,3)))
产生

object: __main__.A
a_array:
- 0, 1, 2
对于一维阵列,以及

object: __main__.A
a_array:
- 1, 1
- 1, 1
- 1, 1
对于二维阵列

=======================================

import numpy as np

class A:
    def __init__(self, anArray):
        self.a_array = anArray

    def __repr__(self):
        astr = ['object: %s'%self.__class__]
        astr.append('a_array:')
        astr.append(self.repr_array())
        return '\n'.join(astr)

    def repr_array(self):
        a = self.a_array
        if a.ndim==1:
            a = a[None,:]
        fmt = ', '.join(['%d']*a.shape[1])
        fmt = '- '+fmt
        astr = []
        for row in a:
             astr.append(fmt%tuple(row))
        astr = '\n'.join(astr)
        return astr

print A(np.arange(3))

print A(np.ones((3,2)))
import yaml
def numpy_representer_str(dumper, data):
    # first cut ndarray yaml representer
    astr = ', '.join(['%s']*data.shape[0])%tuple(data)
    return dumper.represent_scalar('!ndarray:', astr)

def numpy_representer_seq(dumper, data):
    return dumper.represent_sequence('!ndarray:', data.tolist())

yaml.add_representer(np.ndarray, numpy_representer_str)
print (yaml.dump({'a':np.arange(4)},default_flow_style=False))

yaml.add_representer(np.ndarray, numpy_representer_seq)
print (yaml.dump({'a':np.arange(4)},default_flow_style=False))

class A:
    def __init__(self, anArray):
        self.a_array = anArray

    def __repr__(self):
        astr = ['object: %s'%self.__class__]
        astr.append('a_array:')
        astr.append(self.repr_array())
        return '\n'.join(astr)

    def repr_array(self):
        return yaml.dump(self.a_array)
print (A(np.arange(3)))
print (A(np.arange(6).reshape(2,3)))
使用不同风格的numpy representer,我可以得到如下打印效果:

a: !ndarray: '0, 1, 2, 3'   # the string version

a: !ndarray:         # the sequence version
- 0
- 1
- 2
- 3

object: <class '__main__.A'>     # sequence version with 1d
a_array:
!ndarray: [0, 1, 2]

object: <class '__main__.A'>    # sequence version with 2d
a_array:
!ndarray:
- [0, 1, 2]
- [3, 4, 5]
a:!ndarray:'0,1,2,3'#字符串版本
a:!ndarray:#序列版本
- 0
- 1
- 2
- 3
对象:#具有1d的序列版本
一个数组:
!ndarray:[0,1,2]
对象:#具有2d的序列版本
一个数组:
!恩达拉:
- [0, 1, 2]
- [3, 4, 5]

谢谢你,马丁。实际上,我需要将其存储为
数组
,但将其作为列表输出。我想可能有一个
yaml.representer
(或更简单的)解决方案。所有内部计算都将在
数组上进行,数组本身就是内部计算的产物。因此,存储
数组
是很自然的。但是,
yaml
无法很好地打印它(一旦错误得到处理):(假设您的对象仅将
a_数组
存储为成员,您可以执行以下操作:
a=a();转储(a.a_数组.tolist(),默认流样式=False)
。那太简单了。事实上,还有其他类作用域结构,包括嵌套类组合(也需要打印)。现在,我只想重点介绍漂亮的打印
数组
:),谢谢Martin。实际的