2011-04-07 9 views
9

मैं एक अजीब उपवर्ग numpy.ndarray मुद्दा यह है कि
Values of instance variables of superclass persist across instances of subclass
की तरह लगता है हो रहा है लेकिन मैं पूरी तरह से समझते या यह मेरे उदाहरण के लिए के लिए काम करने के लिए नहीं कर पाए हैं भर में जिम्मेदार बताते हैं।numpy सरणी उपवर्ग unexpedly शेयरों उदाहरणों

Slightly more realistic example - attribute added to existing array के माध्यम से पढ़ना मैं वास्तव में बहुत कुछ करने की कोशिश कर रहा हूं। मैं एक शब्दकोश में इकाइयों जैसे सूचना रखने के लिए एक सरणी में एक एटर्स विशेषता जोड़ना चाहता हूं।

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

तो ख उठा attrs कि मैं यह नहीं करना चाहती प्रदर्शित करने के लिए:

यहाँ मैं क्या है। Annoyingly यह ठीक काम करता है अगर आप ऐसा करते हैं:

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 
# {} 
+0

एक सहयोगी ने कहा कि वे इस मुद्दे को सोचा शायद .view() है, हम्म और क्या मैं वहाँ का उपयोग कर सकते हैं? –

+2

थोड़ा सा लगता है [यह महत्वपूर्ण चेतावनी] (http://docs.python.org/tutorial/controlflow.html#default-argument-values)। – lafras

+0

धन्यवाद, यह मुद्दा निश्चित रूप से attrs = {} था, लेकिन जिस तरह से मैं उम्मीद नहीं कर रहा था उसमें खुद को प्रकट किया और मैं देख रहा था .copy() –

उत्तर

16

समस्या यहाँ है:

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

एक समारोह शीर्षक में इस attrs={} करना कभी नहीं। अपेक्षित परिणाम (शायद) नहीं है जो आपको लगता है कि यह है। यह एक आम पायथन Pitfall है। यहाँ देखें Default Parameter Values in Python

सही तरीके से ऐसा करने के तरीके:

def __new__(cls, input_array, attrs=None): 
    if attrs is None: 
     attrs = {} 
+0

ठीक है, यह जवाब है। पिछले .copy() देखें और मेरे द्वारा किए गए तरीके से डिफ़ॉल्ट का उपयोग न करें। धन्यवाद। –

+0

या आप ऐसा कर सकते हैं: 'attrs = attrs या {}' – devxoul

+0

@devxoul - अच्छा विचार, लेकिन यह मेरे लिए विशेष रूप से सुरक्षित प्रतीत नहीं होता है। पाइथन में बहुत सी चीजें 'झूठी' मानी जाती हैं, है ना? मैं उस निर्माण पर भरोसा नहीं करता। – Fenikso

संबंधित मुद्दे