我有一个奇怪的子类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
# {}
答案 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 = {}