2010-05-29 13 views
73

में स्लाइसिंग को कार्यान्वित करना मैं एक वर्ग के लिए स्लाइस कार्यक्षमता को लागू करने की कोशिश कर रहा हूं जो मैं बना रहा हूं जो एक वेक्टर प्रतिनिधित्व बनाता है।पायथन: __getitem__

मेरे पास यह कोड अब तक है, जो मुझे विश्वास है कि टुकड़ा ठीक से लागू करेगा लेकिन जब भी मैं v[4] जैसे कॉल करता हूं, जहां वी वेक्टर पायथन पर्याप्त पैरामीटर नहीं होने के बारे में एक त्रुटि देता है। इसलिए मैं यह समझने की कोशिश कर रहा हूं कि getitem मेरी कक्षा में सादे इंडेक्स और स्लाइसिंग को संभालने के लिए विशेष विधि को कैसे परिभाषित किया जाए।

def __getitem__(self, start, stop, step): 
    index = start 
    if stop == None: 
     end = start + 1 
    else: 
     end = stop 
    if step == None: 
     stride = 1 
    else: 
     stride = step 
    return self.__data[index:end:stride] 

उत्तर

79

__getitem__() विधि जब वस्तु कटा हुआ है एक slice वस्तु प्राप्त होगा। स्लाइस के लिए घटक प्राप्त करने के लिए बस , stop, और stepslice ऑब्जेक्ट के सदस्यों को देखें।

>>> class C(object): 
... def __getitem__(self, val): 
...  print val 
... 
>>> c = C() 
>>> c[3] 
3 
>>> c[3:4] 
slice(3, 4, None) 
>>> c[3:4:-2] 
slice(3, 4, -2) 
>>> c[():1j:'a'] 
slice((), 1j, 'a') 
+5

नोट: सूची या टपल तरह builtins प्रकार देने के लिए आप '2.x पायथन संस्करणों के लिए __getslice__' लागू करता है चाहिए। देखें https://docs.python.org/2/reference/datamodel.html#object.__getslice__ – gregorySalvan

+0

@ग्रीरी साल्वान: क्या उस अनुभाग के नीचे उस संगतता उदाहरण की पुनरावृत्ति नहीं है? – Eric

+1

@Eric: नहीं, क्योंकि दूसरे कोलन की उपस्थिति '__get/set/delslice__' से गुजरती है। हालांकि, यह बहुत सूक्ष्म है। – user2357112

7

यह करने के लिए सही तरीका __getitem__ एक पैरामीटर है, जो या तो एक नंबर, या एक टुकड़ा वस्तु हो सकता है लेने के लिए है।

देखें:

http://docs.python.org/library/functions.html#slice

http://docs.python.org/reference/datamodel.html#object.__getitem__

+1

प्रासंगिक दस्तावेज़ों को जोड़ने के लिए धन्यवाद। – blueshift

54

मैं एक "कृत्रिम" सूची (एक जहां डाटा से बड़ा आप स्मृति में बनाए जाने वाले हैं) और मेरे __getitem__ तरह लग रहा है यह:

def __getitem__(self, key) : 
    if isinstance(key, slice) : 
     #Get the start, stop, and step from the slice 
     return [self[ii] for ii in xrange(*key.indices(len(self)))] 
    elif isinstance(key, int) : 
     if key < 0 : #Handle negative indices 
      key += len(self) 
     if key < 0 or key >= len(self) : 
      raise IndexError, "The index (%d) is out of range."%key 
     return self.getData(key) #Get the data from elsewhere 
    else: 
     raise TypeError, "Invalid argument type." 

टुकड़ा उसी प्रकार को वापस नहीं करता है, जो एक नो- नहीं, लेकिन यह मेरे लिए काम करता है।

+1

यदि कुंजी> = लेन (स्वयं) कुंजी नहीं होनी चाहिए तो < 0 or key > = लेन (स्वयं)? क्या होगा यदि एक कुंजी <-len (स्वयं) पारित हो जाती है? – estan

+0

@estan: मैं मानता हूं, मुझे लगता है कि यह आपके द्वारा उल्लेखित मामले के लिए कवर करना चाहिए। –

+0

@estan आप सही हैं। इसे अभी संपादित करना –

6

दोनों सादे इंडेक्स और स्लाइसिंग को संभालने के लिए गेटिटम क्लास को कैसे परिभाषित किया जाए? और क्या __getitem__ को पारित कर दिया है है कि - जब आप सबस्क्रिप्ट अंकन में एक कॉलन का उपयोग

स्लाइस वस्तुओं स्वचालित रूप से बनाया जाता है।

from __future__ import print_function 

class Sliceable(object): 

    def __getitem__(self, given): 
     if isinstance(given, slice): 
      # do your handling for a slice object: 
      print(given.start, given.stop, given.step) 
     else: 
      # Do your handling for a plain index 
      print(given) 

उदाहरण उपयोग:

>>> sliceme = Sliceable() 
>>> sliceme[1] 
1 
>>> sliceme[2] 
2 
>>> sliceme[:] 
None None None 
>>> sliceme[1:] 
1 None None 
>>> sliceme[1:2] 
1 2 None 
>>> sliceme[1:2:3] 
1 2 3 
>>> sliceme[:2:3] 
None 2 3 
>>> sliceme[::3] 
None None 3 
>>> sliceme[::] 
None None None 
>>> sliceme[:] 
None None None 
3

numpy जैसी चीजों के लिए हारून के जवाब का विस्तार करने के लिए, आप यह देखने के लिए जाँच के द्वारा बहु-आयामी टुकड़ा करने की क्रिया कर सकते हैं अगर आप एक टुकड़ा वस्तु है की जाँच करने के isinstance का प्रयोग करें

class Sliceable(object): 
    def __getitem__(self, given): 
     if isinstance(given, slice): 
      # do your handling for a slice object: 
      print("slice", given.start, given.stop, given.step) 
     elif isinstance(given, tuple): 
      print("multidim", given) 
     else: 
      # Do your handling for a plain index 
      print("plain", given) 

sliceme = Sliceable() 
sliceme[1] 
sliceme[::] 
sliceme[1:, ::2] 

`` `

+०१२३५१६४१०: given एक tuple है

आउटपुट:

('plain', 1) 
('slice', None, None, None) 
('multidim', (slice(1, None, None), slice(None, None, 2))) 
+0

एक मामूली फॉलो-अप के रूप में, यहां [उदाहरण है] (https://github.com/EricCousineau-TRI/repro/blob/62151af/bindings/mlmodule/NumPyProxy.m#L83) MATLAB के बीच मैप करने के लिए इसे नियोजित करने के लिए इंडेक्सिंग और न्यूम्पी इंडेक्सिंग (जो वर्तमान में MATLAB R2016b में समर्थित नहीं है), [उदाहरण उपयोग] के साथ (https://github.com/EricCousineau-TRI/repro/blob/62151af/bindings/mlmodule/test/example_py_slice.m# एल 43) इसके बारे में। –