2011-01-21 10 views
6

[अजगर 3]numpy.ndarray: एक "सामान्य" वर्ग

को बदलने मैं ndarray पसंद है, लेकिन मैं इसे कष्टप्रद उपयोग करने के लिए लगता है।

यहां एक समस्या है जिसका सामना करना पड़ता है। मैं class Array लिखना चाहता हूं जो ndarray की अधिकांश कार्यक्षमता का उत्तराधिकारी होगा, लेकिन तत्काल होने का केवल एक ही तरीका है: एक निश्चित आकार की शून्य-भरे सरणी के रूप में। मैं लिखने के लिए उम्मीद कर रहा था:

class Array(numpy.ndarray): 
    def __init__(size): 
    # What do here? 

मैं एक शून्य से भरे सरणी बनाने के लिए कुछ मानकों के साथ super().__init__ कॉल करना चाहते हैं, लेकिन जब से ndarray एक वैश्विक समारोह numpy.zeros का उपयोग करता है (न कि निर्माता से) यह काम नहीं करेगा एक शून्य भरे सरणी बनाने के लिए।

सवाल:

  1. क्यों कई मामलों में वैश्विक (मॉड्यूल) के बजाय कंस्ट्रक्टर्स कार्यों का उपयोग ndarray करता है? अगर मैं ऑब्जेक्ट उन्मुख सेटिंग में उनका पुन: उपयोग करने की कोशिश कर रहा हूं तो यह एक बड़ी परेशानी है।

  2. मुझे class Array को परिभाषित करने का सबसे अच्छा तरीका क्या है? क्या मुझे ज़ीरो के साथ ndarray मैन्युअल रूप से पॉप्युलेट करना चाहिए, या zeros फ़ंक्शन का पुन: उपयोग करने का कोई तरीका है?

+2

मुझे नहीं लगता कि आप अपनी खुद की कक्षा क्यों बनाना चाहते हैं। 'Numpy.zeros()' फैक्ट्री फ़ंक्शन पर क्या लाभ है? अगर आपको नाम पसंद नहीं है, तो बस इसका नाम बदलें, जैसे 'create_array = numpy.zeros'। –

+0

मुझे अब यकीन नहीं है कि एक फायदा है। शायद मैं कारखाने के समारोह में प्रयोग नहीं किया जाता है। मुझे इसके बारे में सोचना होगा। – max

+0

@Sven Marnach: मैं इस सामान्य विषय पर कई लिंक पाया: http://stackoverflow.com/questions/628950/constructors-vs-factory-methods http://stackoverflow.com/questions/2959871/factory -vs-उदाहरण-कंस्ट्रक्टर्स http://stackoverflow.com/questions/4617311/creation-of-objects-constructors-or-static-factory-methods अन्य भाषाओं से अजगर को कुछ भी नहीं है विशिष्ट है, लेकिन सामान्य टिप्पणी करने लगते हैं लागू करें। और जहां तक ​​मैं कह सकता हूं, कारखाने के कार्यों के लिए वास्तव में कोई नुकसान नहीं है (मेरी निजी वरीयता के अलावा)। – max

उत्तर

6

साथ काम करने के केवल छोटे संशोधनों की आवश्यकता होती है आप ndarray इंटरफेस पसंद नहीं है जाएगा तो यह वारिस नहीं है। आप अपने स्वयं के इंटरफ़ेस को परिभाषित कर सकते हैं और बाकी को ndarray और numpy को सौंप सकते हैं।

import functools 
import numpy as np 


class Array(object): 

    def __init__(self, size): 
     self._array = np.zeros(size) 

    def __getattr__(self, attr): 
     try: return getattr(self._array, attr) 
     except AttributeError: 
      # extend interface to all functions from numpy 
      f = getattr(np, attr, None) 
      if hasattr(f, '__call__'): 
       return functools.partial(f, self._array) 
      else: 
       raise AttributeError(attr) 

    def allzero(self): 
     return np.allclose(self._array, 0) 


a = Array(10) 
# ndarray doesn't have 'sometrue()' that is the same as 'any()' that it has. 
assert a.sometrue() == a.any() == False 
assert a.allzero() 

try: a.non_existent 
except AttributeError: 
    pass 
else: 
    assert 0 
+0

बहुत साफ है। मुझे लगता है कि सभी 'numpy' वैश्विक कार्यों में वही अर्थशास्त्र है जब' ndarray' तर्क के साथ 'ndarray' के समान नाम उदाहरण विधि के रूप में कहा जाता है। – max

+0

पायथन 3 में बदलने के लिए, मैं बस कक्षा परिभाषा से '(ऑब्जेक्ट) 'हटा देता हूं, सही? [ऐसा नहीं है कि इसे छोड़ने से समस्याएं पैदा हो जाएंगी।] – max

+0

@max: कोड 2.x और पायथन 3 पर परिवर्तन किए बिना काम करता है। – jfs

7

कई मामलों में वैश्विक (मॉड्यूल) के बजाय कंस्ट्रक्टर्स कार्यों का उपयोग ndarray क्यों पड़ता है?

  1. संगत/मैटलैब, जहां zeros या ones जैसे कार्यों मूल रूप से आया है के लिए इसी तरह होने के लिए।
  2. वैश्विक कारखाने के कार्य लिखने के लिए जल्दी और समझने में आसान हैं। एक कन्स्ट्रक्टर के अर्थशास्त्र क्या होना चाहिए, उदा। आप एक सिंगल कन्स्ट्रक्टर के साथ एक सरल zeros या empty या ones कैसे व्यक्त करेंगे? वास्तव में, ऐसे कारखाने के काम अन्य प्रोग्रामिंग भाषाओं में भी काफी आम हैं।

class Array है कि मैं जरूरत है परिभाषित करने के लिए सबसे अच्छा तरीका क्या है?

import numpy 

class Array(numpy.ndarray): 
    def __new__(cls, size): 
     result = numpy.ndarray.__new__(Array, size) 
     result.fill(0) 
     return result 
arr = Array(5) 

def test(a): 
    print type(a), a 

test(arr) 
test(arr[2:4]) 
test(arr.view(int)) 

arr[2:4] = 5.5 

test(arr) 
test(arr[2:4]) 
test(arr.view(int)) 

ध्यान दें कि यह अजगर 2 है, लेकिन यह अजगर 3.

+1

कुछ टिप्पणियां: 1. 'ndarray' कन्स्ट्रक्टर के लिए 'आकार' पैरामीटर बस एक टुपल के बजाय एक पूर्णांक हो सकता है। 2. 'dtype = float' डिफ़ॉल्ट है। 3. पायथन 3 में, आप इस मामले में 'सुपर() 'के तर्कों को छोड़ सकते हैं। इन टिप्पणियों का मिश्रण, कन्स्ट्रक्टर की पहली दो पंक्तियां 'सुपर() .__ init __ (आकार)' को कम करती हैं। –

+0

ओह, और मुझे लगता है कि आपका 'सुपर()' कॉल गलत है - पाइथन 2.x में 'सुपर (ऐरे, स्वयं)' होना चाहिए। –

+0

आप सही हैं, मैंने अपना जवाब संपादित कर लिया है। (कन्स्ट्रक्टर हस्ताक्षर सामान्य रूप से अनियंत्रित है।) – Philipp

4

अंडारे का विरासत थोड़ा मुश्किल है। ndarray में विधि __init(self,)___ भी नहीं है, इसलिए इसे उपclass से नहीं कहा जा सकता है, लेकिन इसके कारण हैं। कृपया subclassing के numpy दस्तावेज देखें।

वैसे आप अपनी विशेष आवश्यकताओं के अधिक विशिष्ट हो सकते हैं?अपनी खुद की जरूरतों के लिए एक वर्ग (ndarray का उपयोग) बनाना अभी भी काफी आसान है, लेकिन सभी numpy मशीनरी को पारित करने के लिए ndarray का एक उप-वर्ग काफी अलग मुद्दा है।

ऐसा लगता है कि मैं अपने खुद के पोस्ट टिप्पणी नहीं कर सकता, अजीब
@Philipp: यह अजगर द्वारा बुलाया जाएगा, लेकिन नहीं numpy द्वारा। अंडारे को तुरंत चालू करने के तीन तरीके हैं, और दिशानिर्देश कैसे सभी मामलों को संभालने के लिए दिशानिर्देश दिए गए हैं।

+1

मुझे लगता है कि इस दस्तावेज़ को याद किया है। लेकिन मेरे उदाहरण में '__init__' विधि क्यों कहा जाता है, भले ही 'ndarray''' __new__' था? – Philipp

+0

@ फिलिप: अपने उत्तर पर मेरी टिप्पणी देखें। – max

+0

मैं बस अपनी खुद की कक्षा चाहता था कि मैं पूरी तरह से नियंत्रित करता हूं कि यह कैसे तत्काल है। आप सही subclassing हैं ndarray बहुत मुश्किल है। मैं @ जेएफ में कंटेनर दृष्टिकोण का पालन करूंगा। सेबस्टियन। – max