【问题标题】:numpy array subclass unexpedly shares attributes across instancesnumpy 数组子类意外地跨实例共享属性
【发布时间】:2011-04-07 21:00:09
【问题描述】:

我遇到了一个奇怪的子类 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
# {}

【问题讨论】:

  • 一位同事提到他认为问题可能是 .view(),嗯,我还可以在那里使用什么?
  • 听起来有点像this important warning
  • 谢谢,问题当然出在 attrs={} 上,但以一种出乎我意料的方式表现出来,我一直在查看 .copy()

标签: python numpy


【解决方案1】:

问题出在这里:

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 = {}

【讨论】:

  • 对,这就是答案。查看过去 .copy() 并且不要像我一样使用默认值。谢谢。
  • 或者你可以这样做:attrs = attrs or {}
  • @devxoul - 很酷的想法,但这对我来说似乎并不特别安全。在 Python 中很多东西都被认为是False,不是吗?我不会依赖这种结构。
  • @Fenikso 虽然公平起见,如果您将其他内容完全传入attrs,则不会被视为None,并且该函数仍然会失败,因为它会期望attrs 是一个字典。
  • @Jonathan 好吧,这不是问题。它应该在这种情况下失败,任何期望一些参数并得到不同的函数也是如此。这就是我要说的动态打字功能。当然,你可以检查 dict 的子类,但我会说依赖鸭子类型更 Pythoniac。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-05
  • 2021-01-10
  • 2013-04-05
  • 1970-01-01
  • 1970-01-01
  • 2021-05-04
相关资源
最近更新 更多