подкласс NumPy массива неоправданно разделяет атрибуты между экземплярами - PullRequest
10 голосов
/ 08 апреля 2011

У меня странная проблема с подклассом 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', {})

Итак, чтобы использовать его и продемонстрировать проблему

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....

Значит, б собирает приписки, которые я не хочу. Досадно, что все работает нормально, если вы сделаете это:

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

Так, как в мире я заставляю этот dmarray работать так, как я хочу?


Edit: Итак, похоже, это решает проблему, но я не понимаю, почему. Итак, давайте изменим вопрос на то, что это делает и почему это работает?

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

Таким образом, удалив kwarg из __new__() и поместив его в __init__(), он работает. Я просто попробовал это как "ну, это может сработать"

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

1 Ответ

17 голосов
/ 08 апреля 2011

Проблема здесь:

def __new__(cls, input_array, attrs={})

Никогда не делайте этого attrs={} в заголовке функции. Ожидаемый результат (вероятно) не то, что вы думаете. Это распространенная ошибка Python. Смотрите здесь Значения параметров по умолчанию в Python

Как это сделать:

def __new__(cls, input_array, attrs=None):
    if attrs is None:
        attrs = {}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...