__Getitem__ विधि को समझना


140

मैं __getitem__पायथन डॉक्स के अधिकांश प्रलेखन से गुजरा हूं, लेकिन मैं अभी भी इसका अर्थ समझ नहीं पा रहा हूं।

तो सब मैं समझ सकता हूं कि __getitem__कॉल को लागू करने के लिए उपयोग किया जाता है self[key]। लेकिन इसका क्या फायदा है?

आइए बताते हैं कि मेरे पास एक अजगर वर्ग इस तरह से परिभाषित है:

class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def __getitem__(self,key):
        print ("Inside `__getitem__` method!")
        return getattr(self,key)

p = Person("Subhayan",32)
print (p["age"])

यह अपेक्षित परिणाम देता है। लेकिन __getitem__पहली जगह में क्यों उपयोग करें ? मैंने यह भी सुना है कि पायथन __getitem__आंतरिक रूप से कॉल करता है। लेकिन यह क्यों करता है?

क्या कोई इसे और अधिक विस्तार से बता सकता है?


यह एक उदाहरण के उपयोग के लिए ब्याज की हो सकती है: कैसे ठीक से उपवर्ग को नियंत्रित करें और गेटिटेम
roganjosh

4
__getitem__अपने उदाहरण में उपयोग भावना का एक बहुत नहीं है, लेकिन कल्पना कीजिए कि आप एक कस्टम सूची- या शब्दकोश की तरह वर्ग लिखने के लिए, मौजूदा कोड है कि का उपयोग करता है के साथ काम करने के लिए है कि जरूरत है []। यह एक ऐसी स्थिति है जहाँ __getitem__उपयोगी है।
पीटर विटवेट

जवाबों:


158

Cong Ma समझाने का एक अच्छा काम करता है कि __getitem__इसका उपयोग किस लिए किया जाता है - लेकिन मैं आपको एक उदाहरण देना चाहता हूं जो उपयोगी हो सकता है। एक वर्ग की कल्पना करें जो एक इमारत का मॉडल बनाता है। भवन के लिए डेटा के भीतर इसमें कई विशेषताएं शामिल हैं, जिनमें प्रत्येक मंजिल पर कब्जा करने वाली कंपनियों के विवरण शामिल हैं:

उपयोग किए बिना __getitem__हमारे पास इस तरह एक वर्ग होगा:

class Building(object):
     def __init__(self, floors):
         self._floors = [None]*floors
     def occupy(self, floor_number, data):
          self._floors[floor_number] = data
     def get_floor_data(self, floor_number):
          return self._floors[floor_number]

building1 = Building(4) # Construct a building with 4 floors
building1.occupy(0, 'Reception')
building1.occupy(1, 'ABC Corp')
building1.occupy(2, 'DEF Inc')
print( building1.get_floor_data(2) )

हालाँकि हम बिल्डिंग क्लास के 'अच्छे' का उपयोग करने के लिए __getitem__(और उसके समकक्ष __setitem__) का उपयोग कर सकते हैं ।

class Building(object):
     def __init__(self, floors):
         self._floors = [None]*floors
     def __setitem__(self, floor_number, data):
          self._floors[floor_number] = data
     def __getitem__(self, floor_number):
          return self._floors[floor_number]

building1 = Building(4) # Construct a building with 4 floors
building1[0] = 'Reception'
building1[1] = 'ABC Corp'
building1[2] = 'DEF Inc'
print( building1[2] )

क्या आप __setitem__इस तरह का उपयोग करते हैं यह वास्तव में इस बात पर निर्भर करता है कि आप अपने डेटा को कैसे सार करने की योजना बनाते हैं - इस मामले में हमने एक इमारत को फर्श के कंटेनर के रूप में इलाज करने का फैसला किया है (और आप भवन के लिए एक पुनरावृत्ति भी लागू कर सकते हैं, और शायद टुकड़ा करने की क्षमता भी। - यानी एक समय में एक से अधिक मंजिलों का डेटा प्राप्त करना - यह इस बात पर निर्भर करता है कि आपको क्या चाहिए।


15
बस मैंने कई बार उत्तर को पढ़ने के बाद ही कुछ साझा किया है: एक बार आपके पास एक गेटिटम है जिसे आपको स्पष्ट रूप से उस फ़ंक्शन को कॉल करने की आवश्यकता नहीं है। जब वह building1[2]उस कॉल को खुद आंतरिक रूप से गेटिटेम कहता है। तो बिंदु @ टोनी-घुटन -66 बना रहा है कि, क्लास के किसी भी गुण / चर को रन टाइम के दौरान केवल ऑब्जेक्टनेम [वैरबैलेन] कहकर पुनः प्राप्त किया जा सकता है। बस इसे स्पष्ट करना क्योंकि यह शुरू में मेरे लिए स्पष्ट नहीं था और इसे यहाँ लिखते हुए उम्मीद है कि यह किसी को मदद करता है। कृपया हटाएं यदि अनावश्यक है
मिथुन

3
@mithunpaul ऑब्जेक्ट [इंडेक्स] नोटेशन का उपयोग किसी वर्ग की संपत्ति / चर / विशेषता प्राप्त करने के लिए नहीं किया जाता है - यह एक कंटेनर ऑब्जेक्ट पर isindexing है - उदाहरण के लिए एक माता-पिता से एक बच्चे की वस्तु को पुनः प्राप्त करना जहां माता-पिता बच्चों की एक सूची रखता है। मेरे उदाहरण में - बिल्डिंग क्लास एक कंटेनर है (फ़्लोर नामों के इस मामले में), लेकिन यह फ़्लोर क्लास के लिए एक कंटेनर क्लास हो सकता है।
टोनी सफ़ोक 66 66

सिवाय इसके कि यह समर्थन नहीं करेगा len(), और आपको एक मिलेगा TypeError:TypeError: object of type 'Building' has no len()
Ciasto piekarz

सहायक लेन (और पुनरावृत्ति आदि जैसी अन्य सुविधाएँ) मेरे उदाहरण का उद्देश्य नहीं था। एक dunder_len विधि को लागू करना यद्यपि तुच्छ है।
टोनी सफ़ोकल 66

@ टोनीसुफ़ोक66: क्या यह सही है कि ____len____ आपके उदाहरण में सूचकांक (फर्श) के लिए चलने योग्य निर्धारित करता है, जिस पर ____getitem____ छोरों?
एलेक्स

73

[]कुंजी या सूचकांक द्वारा आइटम प्राप्त करने के लिए वाक्य रचना सिर्फ वाक्य रचना चीनी है।

जब आप a[i]पायथन कॉल का मूल्यांकन करते हैं a.__getitem__(i)(या type(a).__getitem__(a, i), लेकिन यह अंतर वंशानुक्रम मॉडल के बारे में है और यहां महत्वपूर्ण नहीं है)। भले ही वर्ग aस्पष्ट रूप से इस पद्धति को परिभाषित नहीं करता है, यह आमतौर पर पूर्वज वर्ग से विरासत में मिला है।

सभी (पायथन 2.7) विशेष विधि नाम और उनके शब्दार्थ यहां सूचीबद्ध हैं: https://docs.python.org/2.7/reference/datamodel.html#special-method-names


8

जादू की विधि __getitem__मूल रूप से सूची आइटम, शब्दकोश प्रविष्टियों, सरणी तत्वों आदि तक पहुंचने के लिए उपयोग की जाती है। यह उदाहरण के गुणों की त्वरित खोज के लिए बहुत उपयोगी है।

यहाँ मैं इसे एक उदाहरण वर्ग के व्यक्ति के साथ दिखा रहा हूँ जिसे 'नाम', 'आयु' और 'dob' (जन्म तिथि) के द्वारा तत्काल किया जा सकता है। __getitem__विधि इस तरह से लिखी जाती है कि कोई अनुक्रमित इंस्टेंस विशेषताओं तक पहुंच सकता है, जैसे कि पहले या अंतिम नाम, दिन, महीने या वर्ष के वर्ष।

import copy

# Constants that can be used to index date of birth's Date-Month-Year
D = 0; M = 1; Y = -1

class Person(object):
    def __init__(self, name, age, dob):
        self.name = name
        self.age = age
        self.dob = dob

    def __getitem__(self, indx):
        print ("Calling __getitem__")
        p = copy.copy(self)

        p.name = p.name.split(" ")[indx]
        p.dob = p.dob[indx] # or, p.dob = p.dob.__getitem__(indx)
        return p

मान लीजिए कि एक उपयोगकर्ता इनपुट इस प्रकार है:

p = Person(name = 'Jonab Gutu', age = 20, dob=(1, 1, 1999))

__getitem__विधि की मदद से , उपयोगकर्ता अनुक्रमित विशेषताओं तक पहुंच सकता है। जैसे,

print p[0].name # print first (or last) name
print p[Y].dob  # print (Date or Month or ) Year of the 'date of birth'

महान उदाहरण! मैं सभी के बारे में खोज कर रहा था कि गेटिटेम को कैसे लागू किया जाए जब init के कई पैरामीटर हैं और मैं एक उचित कार्यान्वयन खोजने के लिए संघर्ष कर रहा था और अंत में इसे समाप्त कर दिया! Upvoted और धन्यवाद!
राहुल पी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.