numpy数组子类不成功地跨实例共享属性

时间:2011-04-07 21:00:09

标签: python numpy

我有一个奇怪的子类numpy.ndarray问题,感觉就像是 Values of instance variables of superclass persist across instances of subclass
但是我无法完全理解或者为我的例子而努力。

阅读 Slightly more realistic example - attribute added to existing array我正在努力做到这一点。我想在数组中添加一个attrs属性来保存字典中的单位等信息。

这就是我所拥有的:

import numpy
class dmarray(numpy.ndarray):
    def __new__(cls, input_array, attrs={}):
        obj = numpy.asarray(input_array).view(cls)
        obj.attrs = attrs
        return obj

    def __array_finalize__(self, obj):
        # see InfoArray.__array_finalize__ for comments
        if obj is None:
            return
        self.attrs = getattr(obj, 'attrs', {})

然后使用它并演示问题

a = dmarray([1,2,3,4])
b = dmarray([1,2,3,4])
a.attrs['foo'] = 'bar'
print(b.attrs)
#{'foo': 'bar'}
b.attrs is a.attrs
# True  # hmm....

所以b正在挑选我不想要的人。令人讨厌的是,如果你这样做,它可以正常工作:

from datamodel import *
a = dmarray([1,2,3,4], attrs={'foo':'bar'})
b = dmarray([1,2,3,4])
b.attrs
# {}

那么我是如何让这个dmarray按照我想要的方式工作呢?


编辑: 好吧所以这似乎解决了问题,但我不明白为什么。那么让我们把问题改成这是做什么以及它为什么起作用?

class dmarray(numpy.ndarray):
    def __new__(cls, input_array, attrs=None):
        obj = numpy.asarray(input_array).view(cls)
        return obj

    def __init__(self, input_array, attrs=None):
        if attrs == None:
            attrs = {}
        self.attrs = attrs

因此,从__new__()移除kwarg并将其放入__init__()即可。我只是尝试了这个“它可能有效”

a = dmarray([1,2,3,4])
b = dmarray([1,2,3,4])
a.attrs['foo'] = 'bar'
b.attrs
# {}

1 个答案:

答案 0 :(得分:17)

问题在于:

def __new__(cls, input_array, attrs={})

永远不要在函数标题中执行此操作attrs={}。预期的结果(可能)不是你认为的那样。这是一个常见的Python陷阱。见Default Parameter Values in Python

正确的方法:

def __new__(cls, input_array, attrs=None):
    if attrs is None:
        attrs = {}