[Python] स्वयं का उद्देश्य क्या है?



Answers

चलो एक साधारण वेक्टर कक्षा लेते हैं:

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

हम एक विधि चाहते हैं जो लंबाई की गणना करे। ऐसा लगता है कि हम इसे कक्षा के अंदर परिभाषित करना चाहते हैं?

    def length(self):
        return math.sqrt(self.x ** 2 + self.y ** 2)

जब हमें इसे वैश्विक विधि / फ़ंक्शन के रूप में परिभाषित करना था, तो यह कैसा दिखना चाहिए?

def length_global(vector):
    return math.sqrt(vector.x ** 2 + vector.y ** 2)

तो पूरी संरचना वही रहती है। मैं इसका उपयोग कैसे कर सकता हूं? अगर हम एक पल के लिए मानते हैं कि हमने अपने Vector वर्ग के लिए length विधि नहीं लिखी है, तो हम यह कर सकते हैं:

Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0

यह काम करता है क्योंकि length_global का पहला पैरामीटर, length_global में self पैरामीटर के रूप में पुन: उपयोग किया जा सकता है। यह एक स्पष्ट self बिना संभव नहीं होगा।

स्पष्ट self की आवश्यकता को समझने का एक और तरीका यह देखना है कि पाइथन कुछ वाक्य रचनात्मक चीनी कहां जोड़ता है। जब आप ध्यान में रखते हैं, मूल रूप से, एक कॉल की तरह

v_instance.length()

आंतरिक रूप से बदल दिया गया है

Vector.length(v_instance)

यह देखना आसान है कि self कहां फिट बैठता है। आप वास्तव में पायथन में उदाहरण विधियां नहीं लिखते हैं; जो आप लिखते हैं वह वर्ग विधियां है जो पहले पैरामीटर के रूप में एक उदाहरण लेना चाहिए। और इसलिए, आपको कहीं भी उदाहरण पैरामीटर को स्पष्ट रूप से रखना होगा।

Question

पायथन में self शब्द का उद्देश्य क्या है? मैं समझता हूं कि यह उस वर्ग से बनाए गए विशिष्ट ऑब्जेक्ट को संदर्भित करता है, लेकिन मैं नहीं देख सकता कि पैरामीटर के रूप में प्रत्येक फ़ंक्शन में इसे स्पष्ट रूप से क्यों जोड़ा जाना चाहिए। उदाहरण के लिए, रूबी में मैं यह कर सकता हूं:

class myClass
    def myFunc(name)
        @name = name
    end
end

जो मैं समझता हूं, काफी आसानी से। हालांकि पायथन में मुझे self को शामिल करने की आवश्यकता है:

class myClass:
    def myFunc(self, name):
        self.name = name

क्या कोई इस के माध्यम से मुझसे बात कर सकता है? यह ऐसा कुछ नहीं है जो मैंने अपने (स्वीकार्य रूप से सीमित) अनुभव में पार किया है।




मैं कोड के साथ प्रदर्शित करूंगा जो वर्गों का उपयोग नहीं करता है :

def state_init(state):
    state['field'] = 'init'

def state_add(state, x):
    state['field'] += x

def state_mult(state, x):
    state['field'] *= x

def state_getField(state):
    return state['field']

myself = {}
state_init(myself)
state_add(myself, 'added')
state_mult(myself, 2)

print( state_getField(myself) )
#--> 'initaddedinitadded'

कक्षाएं इस "राज्य" चीज में हर समय गुजरने से बचने के लिए एक तरीका हैं (और अन्य अच्छी चीजें जैसे प्रारंभिक, कक्षा संरचना, शायद ही कभी आवश्यक मेटाक्लास, और ऑपरेटरों को ओवरराइड करने के लिए कस्टम तरीकों का समर्थन करना)।

अब अंतर्निहित पाइथन वर्ग मशीनरी का उपयोग करके उपरोक्त कोड का प्रदर्शन करें, यह दिखाने के लिए कि यह मूल रूप से वही चीज़ है।

class State(object):
    def __init__(self):
        self.field = 'init'
    def add(self, x):
        self.field += x
    def mult(self, x):
        self.field *= x

s = State()
s.add('added')    # self is implicitly passed in
s.mult(2)         # self is implicitly passed in
print( s.field )

[डुप्लिकेट बंद प्रश्न से मेरा जवाब माइग्रेट किया]




ऐसा इसलिए है क्योंकि जिस तरह से पाइथन डिजाइन किए गए हैं, वैसे ही विकल्प शायद ही काम करेंगे। पाइथन को किसी संदर्भ में विधियों या कार्यों को परिभाषित करने की अनुमति देने के लिए डिज़ाइन किया गया है, जहां दोनों this (ए-ला जावा / सी ++) या स्पष्ट @ (ए-ला रूबी) काम नहीं करेगा। चलो पाइथन सम्मेलनों के साथ स्पष्ट दृष्टिकोण के साथ एक उदाहरण है:

def fubar(x):
    self.x = x

class C:
    frob = fubar

अब fubar फ़ंक्शन काम नहीं करेगा क्योंकि यह मान लेगा कि self एक वैश्विक चर है (और frob में भी)। वैकल्पिक रूप से प्रतिस्थापित वैश्विक दायरे के साथ विधि निष्पादित करना होगा (जहां self वस्तु है)।

अंतर्निहित दृष्टिकोण होगा

def fubar(x)
    myX = x

class C:
    frob = fubar

इसका मतलब यह होगा कि myX को myX में स्थानीय चर के रूप में व्याख्या किया जाएगा (और frob में भी)। यहां विकल्प एक स्थानीय स्थान के साथ विधियों को निष्पादित करना होगा जो कॉल के बीच बनाए रखा जाता है, लेकिन यह स्थानीय चर के तरीके की सकारात्मकता को हटा देगा।

हालांकि वर्तमान स्थिति अच्छी तरह से काम करती है:

 def fubar(self, x)
     self.x = x

 class C:
     frob = fubar

यहां एक विधि frob रूप में बुलाया जाने वाला ऑब्जेक्ट उस ऑब्जेक्ट को प्राप्त करेगा जिस पर इसे self पैरामीटर के माध्यम से बुलाया जाता है, और fubar को अभी भी ऑब्जेक्ट के साथ पैरामीटर के रूप में बुलाया जा सकता है और यह वही काम करता है (यह C.frob मुझे लगता है) जैसा ही है।




self ऑब्जेक्ट का ऑब्जेक्ट संदर्भ है, इसलिए, वे समान हैं। पाइथन विधियों को ऑब्जेक्ट के संदर्भ में नहीं कहा जाता है। पाइथन में self कस्टम ऑब्जेक्ट मॉडल या किसी चीज़ से निपटने के लिए उपयोग किया जा सकता है।




पायथन जावा या सी ++ के विपरीत ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग के लिए बनाई गई भाषा नहीं है।

पाइथन में एक स्थिर विधि को कॉल करते समय, कोई बस इसके अंदर नियमित तर्क के साथ एक विधि लिखता है।

class Animal():
    def staticMethod():
        print "This is a static method"

हालांकि, एक ऑब्जेक्ट विधि, जिसके लिए आपको एक चर बनाने की आवश्यकता होती है, जो एक पशु है, इस मामले में, स्वयं तर्क की आवश्यकता होती है

class Animal():
    def objectMethod(self):
        print "This is an object method which needs an instance of a class"

वर्ग के भीतर एक चर क्षेत्र को संदर्भित करने के लिए स्वयं विधि का भी उपयोग किया जाता है।

class Animal():
    #animalName made in constructor
    def Animal(self):
        self.animalName = "";


    def getAnimalName(self):
        return self.animalName

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

यदि आप जो भी कह रहे हैं, उसके एक शब्द को नहीं समझते हैं, तो Google "ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग"। एक बार जब आप इसे समझ लेंगे, तो आपको उस प्रश्न से पूछने की भी आवश्यकता नहीं होगी :)।




यह क्लास इंस्टेंस ऑब्जेक्ट का एक स्पष्ट संदर्भ है।




मुझे आश्चर्य है कि कोई भी लुआ लाया नहीं है। लुआ भी 'स्वयं' चर का उपयोग करता है हालांकि इसे छोड़ा जा सकता है लेकिन अभी भी उपयोग किया जा सकता है। सी ++ 'इस' के साथ समान है। मुझे प्रत्येक फ़ंक्शन में 'स्वयं' घोषित करने का कोई कारण नहीं दिखता है, लेकिन आपको अभी भी इसका उपयोग करने में सक्षम होना चाहिए जैसे आप लुआ और सी ++ के साथ कर सकते हैं। ऐसी भाषा के लिए जो संक्षिप्त होने पर खुद की प्रशंसा करता है, यह अजीब बात है कि आपको स्वयं परिवर्तनीय घोषित करने की आवश्यकता है।




निम्नलिखित अंश पाइथन दस्तावेज से स्वयं के बारे में हैं :

मॉडुला -3 में, ऑब्जेक्ट के सदस्यों को इसके तरीकों से संदर्भित करने के लिए [पायथन] में कोई शॉर्टेंड नहीं हैं: विधि फ़ंक्शन को ऑब्जेक्ट का प्रतिनिधित्व करने वाले एक स्पष्ट पहले तर्क के साथ घोषित किया जाता है, जिसे कॉल द्वारा स्पष्ट रूप से प्रदान किया जाता है।

अक्सर, विधि के पहले तर्क को स्वयं कहा जाता है। यह एक सम्मेलन से ज्यादा कुछ नहीं है: नाम स्वयं के पास पाइथन के लिए बिल्कुल विशेष अर्थ नहीं है। नोट, हालांकि, सम्मेलन का पालन न करके आपका कोड अन्य पायथन प्रोग्रामर के लिए कम पठनीय हो सकता है, और यह भी कल्पना की जा सकती है कि एक क्लास ब्राउज़र प्रोग्राम लिखा जा सकता है जो इस तरह के एक सम्मेलन पर निर्भर करता है।

अधिक जानकारी के लिए, कक्षाओं पर पायथन दस्तावेज़ ट्यूटोरियल देखें।




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

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

ऑब्जेक्ट स्वयं पैरामीटर में पारित किया जाता है ताकि ऑब्जेक्ट अपने डेटा को रोक सके।

यद्यपि यह पूरी तरह से सटीक नहीं हो सकता है, इस तरह की किसी ऑब्जेक्ट को तुरंत चालू करने की प्रक्रिया के बारे में सोचें: जब कोई ऑब्जेक्ट बनाया जाता है तो यह क्लास को अपने डेटा और विधियों के लिए टेम्पलेट के रूप में उपयोग करता है। स्वयं पैरामीटर में अपना नाम पारित किए बिना, कक्षा में गुण और विधियां सामान्य टेम्पलेट के रूप में बनी रहेंगी और ऑब्जेक्ट के संदर्भ में संदर्भित नहीं किए जाएंगे। तो ऑब्जेक्ट का नाम स्वयं पैरामीटर में पास करके इसका मतलब है कि यदि एक वर्ग से 100 ऑब्जेक्ट्स को तुरंत चालू किया जाता है, तो वे सभी अपने डेटा और विधियों का ट्रैक रख सकते हैं।

नीचे दिए गए चित्र देखें:






Links