numpy数组子类在实例之间意外共享属性 [英] numpy array subclass unexpedly shares attributes across instances
问题描述
我遇到了一个奇怪的子类numpy.ndarray问题,感觉像是
超类实例变量的值在子类
但是我无法完全理解或使其适用于我的示例.
I am having a weird subclass numpy.ndarray issue that feels like
Values of instance variables of superclass persist across instances of subclass
But I have not been able to understand fully or make it work for for my example.
Reading through Slightly more realistic example - attribute added to existing array I am trying to do pretty much exactly this. I want to add an attrs attribute to an array to hold information such as units in a dictionary.
这就是我所拥有的:
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正在获取我不想要的attrs.令人讨厌的是,如果您这样做,它会很好:
So b is picking up attrs that I don't want it to. Annoyingly it works fine if you do this:
from datamodel import *
a = dmarray([1,2,3,4], attrs={'foo':'bar'})
b = dmarray([1,2,3,4])
b.attrs
# {}
那么,我到底如何使dmarray发挥作用?
So how in the world do I make this dmarray work how I want it to?
好的,这似乎可以解决问题,但是我不明白为什么.因此,让我们将问题更改为正在执行的操作以及它为什么起作用?
OK so this seems to fix the problem but I don't understand why. So lets change the question to what this is doing and why it works?
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__()
中,它可以工作.我只是尝试这样做,因为它可能会起作用"
So by removing the kwarg from __new__()
and putting it in __init__()
it works. I just tried this as a "well it might work"
a = dmarray([1,2,3,4])
b = dmarray([1,2,3,4])
a.attrs['foo'] = 'bar'
b.attrs
# {}
推荐答案
问题在这里:
def __new__(cls, input_array, attrs={})
永远不要在函数头中执行此attrs={}
.预期的结果(可能)不是您认为的那样.这是一个常见的Python陷阱.请参见 Python中的默认参数值
Never do this attrs={}
in a function header. The expected result is (probably) not what you think it is. This is a common Python Pitfall. See here Default Parameter Values in Python
正确的方法:
def __new__(cls, input_array, attrs=None):
if attrs is None:
attrs = {}
这篇关于numpy数组子类在实例之间意外共享属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!