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

Bri*_*sen 10 python numpy

我有一个奇怪的子类numpy.ndarray问题,感觉像
超类的实例变量的值在子类的实例中持久
但我无法完全理解或使其适用于我的示例.

阅读 稍微更现实的例子 - 添加到现有数组的属性我正试图做到这一点.我想在数组中添加一个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', {})
Run Code Online (Sandbox Code Playgroud)

那么使用它并演示问题

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....
Run Code Online (Sandbox Code Playgroud)

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

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

那么我在世界上如何使这个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
Run Code Online (Sandbox Code Playgroud)

因此,通过移除kwarg __new__()并将其放入__init__()其中.我只是尝试了这个"它可能有效"

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

Fen*_*kso 17

问题出在这里:

def __new__(cls, input_array, attrs={})
Run Code Online (Sandbox Code Playgroud)

切勿attrs={}在函数头中执行此操作.预期的结果(可能)不是你认为的那样.这是一个常见的Python陷阱.请参阅此处Python中的默认参数值

正确的方法如何做到这一点:

def __new__(cls, input_array, attrs=None):
    if attrs is None:
        attrs = {}
Run Code Online (Sandbox Code Playgroud)