numpy数组子类在实例之间意外共享属性 [英] numpy array subclass unexpedly shares attributes across instances

查看:51
本文介绍了numpy数组子类在实例之间意外共享属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个奇怪的子类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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆