The स्व ’शब्द का उद्देश्य क्या है?


1130

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

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

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

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

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


111
आपको गुइडो वैन रोसुम
unutbu

14
यह भी देखें कि "स्व 'का प्रयोग विधि परिभाषाओं और कॉलों में स्पष्ट रूप से क्यों किया जाना चाहिए": docs.python.org/faq/…
unutbu

37
"जो मैं समझता हूं, काफी आसानी से" --- बहुत व्यक्तिपरक, क्या आपको नहीं लगता? से @nameअधिक सहज क्या है self.name? बाद वाला, IMO, अधिक सहज है।
सांता

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

9
मुझे नहीं लगता कि "स्पष्ट रूप से निहित से बेहतर है" वास्तव में इस डिजाइन की पसंद को अच्छी तरह से समझाता है। @fooऔर self.fooसमान रूप से स्पष्ट हैं क्योंकि कोई अंतर्निहित संकल्प होने की आवश्यकता नहीं है (उदाहरण के लिए C ++ में, उदाहरण के सदस्यों को "स्पष्ट रूप से" बिना नाम के उपयोग के "स्पष्ट रूप से" एक्सेस किया जा सकता है)। अंतर केवल इतना है कि रूबी एक नए शब्दार्थ (@) का परिचय देती है, जबकि पायथन नहीं करता है। एक नया शब्दार्थ वर्बोसिटी की मात्रा के लायक था जो पूरी तरह से व्यक्तिपरक है। हालांकि, यह ध्यान दिया जाना चाहिए कि अधिकांश आधुनिक भाषाएं यहां एक अवधारणा पेश करना पसंद करती हैं (जैसे कि php $ यह, JS का यह)।
जिंग

जवाबों:


710

आपके द्वारा उपयोग किए जाने self.का कारण है क्योंकि पायथन @उदाहरण विशेषताओं को संदर्भित करने के लिए सिंटैक्स का उपयोग नहीं करता है । पायथन ने ऐसे तरीकों से करने का फैसला किया जो उस उदाहरण को बनाते हैं जिससे विधि स्वचालित रूप से पास हो जाती है, लेकिन स्वचालित रूप से प्राप्त नहीं होती है: विधियों का पहला पैरामीटर उदाहरण है जिस पद्धति को कहा जाता है। यह पूरी तरह से कार्य के रूप में विधियां बनाता है, और वास्तविक नाम को आपके ऊपर उपयोग करने के लिए छोड़ देता है (हालांकि selfसम्मेलन है, और लोग आमतौर पर जब आप किसी और चीज का उपयोग करते हैं तो आप पर फेंक देंगे।) selfकोड के लिए विशेष नहीं है, यह सिर्फ एक और वस्तु है। ।

पायथन ने सामान्य नामों को विशेषताओं से अलग करने के लिए कुछ और किया हो सकता है - रूबी की तरह विशेष वाक्यविन्यास, या सी ++ और जावा जैसी घोषणाओं की आवश्यकता होती है, या शायद अभी तक कुछ अलग है - लेकिन यह नहीं हुआ। पाइथन की सभी चीजें स्पष्ट करने के लिए, यह स्पष्ट कर देता है कि क्या है, और यद्यपि यह पूरी तरह से हर जगह ऐसा नहीं करता है, उदाहरण के लिए यह करता है। इसलिए एक उदाहरण विशेषता को निर्दिष्ट करना यह जानना आवश्यक है कि किस उदाहरण को निर्दिष्ट किया जाना चाहिए, और इसीलिए इसकी आवश्यकता है self.


23
@Georg: clsक्लास ऑब्जेक्ट को संदर्भित करता है, न कि ऑब्जेक्ट ऑब्जेक्ट
साइलेंटगॉस्ट

17
@SilentGhost: दरअसल, पहले पैरामीटर का नाम वह है जो आप चाहते हैं कि यह हो। क्लास के तरीकों पर, कन्वेंशन का उपयोग करना है clsऔर selfउदाहरण के तरीकों के लिए पारंपरिक रूप से उपयोग किया जाता है। अगर मैं चाहता था, मैं selfclassmethods के लिए और clsउदाहरण के तरीकों के लिए उपयोग कर सकते हैं । मैं भी इस्तेमाल कर सकता था bobऔर fnordअगर मुझे पसंद आया।
एकलकरण

67
मुझे यह दिलचस्प लगा कि समुदाय ने thisइसके बजाय चयन नहीं किया self। क्या selfकुछ इतिहास है जो मुझे पुरानी प्रोग्रामिंग भाषाओं में पता नहीं है?
जूल्स जीएम

24
@ जूलियस मोडुला self-3 के सम्मेलनों से आया था, इस विकल्प पर आगे के विवरण के लिए यह उत्तर देखें । (डिस्क्लेमर: इसकी खान)।
बकुरीउ

9
@ जूलियस selfकीवर्ड (स्मॉलटाक, 1980) thisकीवर्ड (C ++ से) से पहले का है । देखें: stackoverflow.com/questions/1079983/…
वेस टर्नर

425

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

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)

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

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

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


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

v_instance.length()

आंतरिक रूप से रूपांतरित हो जाता है

Vector.length(v_instance)

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


4
Vector.length_new = length_global ... मैंने वास्तव में अपनी कक्षा की घोषणाओं में इस तरह वाक्य रचना का उपयोग करना शुरू कर दिया था। जब भी मैं केवल कुछ विधियों को किसी अन्य वर्ग से विरासत में लेना चाहता हूं, तो मैं केवल तरीकों के संदर्भ को स्पष्ट रूप से कॉपी करता हूं।
Jeeyoung किम

2
क्या यह कहना उचित होगा कि पायथन की "इंस्टेंस विधि" स्थैतिक वैश्विक विधियों का एक मात्र शर्करा है (जैसा कि जावा या C ++ में) एक उदाहरण ऑब्जेक्ट के साथ कई विशेषताओं को पैकेज करने के लिए पारित किया गया है? --- अच्छी तरह से यह बहुरूपता के बाद से आधा सच है, "यह" (जावा में) या "स्वयं" का अधिक महत्वपूर्ण उद्देश्य यू को तरीकों का सही कार्यान्वयन देना है। अजगर के पास यह है। इसलिए myobj.someMethod () कॉलिंग अजगर में TheClassOfMyObj.someMethod (myobj) के बराबर है। ध्यान दें कि "TheClassOfMyObj" को स्वचालित रूप से "स्व" से अजगर द्वारा पता लगाया गया है, अन्यथा आपको यह पता लगाना होगा।
टेडी टेडी

3
वास्तव में, न केवल उदाहरण विधियां सिर्फ वर्ग विधियां हैं, बल्कि विधियां केवल कार्य हैं जो एक वर्ग के सदस्य हैं, जैसे कि Vector.length_new = length_globalशो।
रसेल

1
"यह काम करता है, क्योंकि length_global का पहला पैरामीटर, length_new में सेल्फ पैरामीटर के रूप में फिर से उपयोग किया जा सकता है। यह एक स्पष्ट स्व के बिना संभव नहीं होगा।" - यह सिर्फ एक ही काम करेगा। यह अंतर्निहित स्व के लिए फिर से उपयोग किया जाएगा ... दूसरा उदाहरण एक परिपत्र तर्क है - आपको स्पष्ट रूप से स्वयं को जगह देना होगा, क्योंकि अजगर को स्पष्ट स्व की आवश्यकता होती है।
कारोली होर्वाथ

1
@KarolyHorvath: निश्चित रूप से, एक मॉडल के साथ एक भाषा होना भी संभव होगा जहां आंतरिक रूप से परिभाषित तरीकों को एक स्पष्ट स्वयं की आवश्यकता नहीं होती है, लेकिन बाहरी रूप से परिभाषित तरीकों की आवश्यकता होती है। लेकिन मैं कहूंगा कि दोनों मामलों में स्पष्ट स्व की आवश्यकता होने में कुछ स्थिरता है, जो इसे इस तरह से करने का एक वैध कारण है। अन्य भाषाएँ अलग-अलग दृष्टिकोण चुन सकती हैं।
डेबिल्स्की

420

मान लीजिए कि आपके पास एक वर्ग है ClassAजिसमें एक विधि methodAइस प्रकार है:

def methodA(self, arg1, arg2):
    # do something

तथा ObjectA इस वर्ग का एक उदाहरण है।

जब ObjectA.methodA(arg1, arg2)कहा जाता है, अजगर आंतरिक रूप से आपके लिए इसे रूपांतरित करता है:

ClassA.methodA(ObjectA, arg1, arg2)

selfचर वस्तु ही को दर्शाता है।


94
मैंने अन्य सभी उत्तरों और प्रकारों को समझा, मैंने इसे पढ़ा और फिर यह सब समझ में आया।
सेठ

3
यह मेरे लिए यह किसी को भी नहीं!
बर्नार्ड 'बीटा बर्लिन' पराह

2
क्यों नहीं उन हिम्मत के अंदर, हालांकि, रूबी की तरह?
सेस टिम्मरमैन

लेकिन __in __ (स्व) विधि में, यह स्वयं को स्वीकार करता है, फिर भी वस्तु का निर्माण किए बिना, यह स्वयं को कैसे संदर्भित करता है?
saurav

गंभीरता से, यह देबिल्स्की के उदाहरण से बहुत बेहतर है क्योंकि यह अत्यधिक जटिल नहीं है और लोग वैक्टर से परिचित नहीं हो सकते हैं।
NoName

215

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

यहां छवि विवरण दर्ज करें

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

यहां छवि विवरण दर्ज करें

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

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

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

यहां छवि विवरण दर्ज करें


देखिए, जब "bob.name ()" उदाहरण के लिए बॉब की विशेषताओं तक पहुँचने, आप वास्तव में बॉब में जाकर ()। Self.name तो 'से बात करने के लिए init ' है ना?
udarH3

3
जब आप उपरोक्त टिप्पणी में bob.name () लिखते हैं, तो आप यह मान रहे हैं कि बॉब के पास नाम () के कारण एक विधि है, जिसके कारण आपने नाम के बाद कोष्ठक जोड़े हैं। इस उदाहरण में हालांकि ऐसी कोई विधि नहीं है। 'bob.name' (जिसमें कोई कोष्ठक नहीं है) सीधे init (कंस्ट्रक्टर) विधि से नाम नामक विशेषता तक पहुंच रहा है। जब बॉब की बोलने की विधि को कहा जाता है तो यह वह विधि है जो नाम विशेषता तक पहुँचती है और इसे प्रिंट स्टेटमेंट में वापस करती है। उम्मीद है की यह मदद करेगा।
sw123456

3
नहीं, आपको self.name का मान मिलता है, जो कि बॉब ऑब्जेक्ट के लिए वास्तव में bob.name है, क्योंकि ऑब्जेक्ट का नाम स्वयं पैरामीटर में तब बनाया जाता है जब इसे बनाया जाता है (त्वरित)। फिर, उम्मीद है कि यह मदद करता है। अगर यह है तो मुख्य पोस्ट को उभारने के लिए स्वतंत्र महसूस करें।
sw123456

2
नाम को तात्कालिकता के लिए self.name सौंपा गया है। किसी ऑब्जेक्ट के बनने के बाद, सभी चर जो ऑब्जेक्ट से संबंधित होते हैं, वे 'स्व' के साथ उपसर्ग होते हैं। याद रखें कि कक्षा से निर्मित होने पर ऑब्जेक्ट को ऑब्जेक्ट के नाम से बदल दिया जाता है।
sw123456

5
इस तरह आप सामान समझाते हैं! अच्छा काम :)
penta

80

मुझे यह उदाहरण पसंद है:

class A: 
    foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: [5]

class A: 
    def __init__(self): 
        self.foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: []

18
स्वयं के बिना इतनी भिन्नताएं केवल कक्षा के स्थिर संस्करण हैं, जैसे जावा में
टेडी टेडी

5
टेडी टेडी, आप पूरी तरह से सही नहीं हैं। व्यवहार (स्थिर या गैर-स्थिर की तरह) न केवल पर selfबल्कि चर प्रकार पर भी निर्भर करता है । सूची के बजाय सरल पूर्णांक के साथ पहला उदाहरण करने का प्रयास करें। परिणाम काफी अलग होगा।
कॉन्सटेंटिन

2
दरअसल, इसके साथ मेरा सवाल यह है कि आपको a.fooपहले उदाहरण के बजाय कहने की अनुमति क्यों दी जाती है A.foo? स्पष्ट रूप fooसे वर्ग के अंतर्गत आता है ...
रेडॉन रोसबोरो

आप स्थैतिक सदस्यों को अधिकांश भाषाओं में ऑब्जेक्ट के उदाहरणों से कॉल कर सकते हैं। क्यों हैरानी की बात है?
पार्थ

2
@RadonRosborough क्योंकि पहले उदाहरण में, aऔर (वर्ग) के bलिए दोनों लेबल (या संकेत A()) हैं। वर्ग विधि का a.fooसंदर्भ देता है A().foo। दूसरे उदाहरण में, हालांकि, aएक के लिए एक संदर्भ हो जाता है उदाहरण के A(), के रूप में करता है b। अब जब वे क्लास ऑब्जेक्ट के बजाय उदाहरण हैं, तो स्वयंfoo इंस्टेंसेस पर काम करने की विधि की अनुमति देता है ।
लेजेंडरीडूड

40

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

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 )

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


1
मैं चाहता हूं कि पाइथन ने हैंडलर के साथ-साथ रूबी को भी शक्कर दी।
सेस टिम्मरमैन

20

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

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

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

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


20

पहले से ही बताए गए अन्य सभी कारणों के साथ, यह ओवरराइड विधियों के लिए आसान पहुंच की अनुमति देता है; आप कॉल कर सकते हैं Class.some_method(inst)

इसका एक उदाहरण जहां यह उपयोगी है:

class C1(object):
    def __init__(self):
         print "C1 init"

class C2(C1):
    def __init__(self): #overrides C1.__init__
        print "C2 init"
        C1.__init__(self) #but we still want C1 to init the class too
>>> C2()
"C2 init"
"C1 init"

17

इसका उपयोग thisजावा में कीवर्ड के उपयोग के समान है , अर्थात वर्तमान वस्तु का संदर्भ देने के लिए।


2
वर्ग myClass: def myFunc (यह, नाम): this.name = नाम
LEMUEL ADANE

16

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

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

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 "ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग" है। एक बार जब आप इसे समझ जाते हैं, तो आपको उस प्रश्न को पूछने की भी आवश्यकता नहीं होगी :)।


के बीच अंतर की वजह से +1 staticMethod()और objectMethod(self)। मैं जोड़ने के लिए पहले आह्वान करने के लिए, आप का कहना है कि चाहते हैं Animal.staticMethod(), जबकि objectMethod()जरूरत है एक उदाहरण:a = Animal(); a.objectMethod()
Laryx पत्या

आप जो कह रहे हैं वह 100% सत्य नहीं है। वह सिर्फ एक सम्मेलन है। आप अभी भी बनाए गए ऑब्जेक्ट से स्थिर विधि को कॉल कर सकते हैं। आप किसी भी वर्ग के सदस्यों का उपयोग करने में सक्षम नहीं होंगे क्योंकि आपने स्वयं को घोषित नहीं किया था। मैं भी गैर स्थिर कॉल करने के लिए Animal.objectMethod (animalObj) कॉल कर सकते हैं। मूल रूप से इसका मतलब है कि एक स्थिर विधि केवल एक विधि है जो सदस्य चर का उपयोग नहीं करती है। स्वयं को घोषित करने की कोई आवश्यकता नहीं होनी चाहिए। मुझे लगता है कि यह एक मूर्खतापूर्ण भाषा की आवश्यकता है। लुआ और सी ++ जैसी भाषाएं आपको पर्दे के पीछे के चर देती हैं।
user441521

आपने एक बेकार पशु का नामकरण स्ट्रिंग घोषणा और दुर्घटनाग्रस्त पशु नाम विधि बनाया।
सेस टिम्मरमैन

3
@ytpillai अप्रासंगिक। भ्रमित और गलत कोड को एक उत्तर के रूप में प्रस्तुत नहीं किया जाना चाहिए।
सेस टिम्मरमैन

1
def getAnimalNameजिस स्ट्रिंग को आप वापस करने की कोशिश कर रहे हैं, उसे क्लोब करने के लिए नहीं, और selfइसके अंदर किसी भी क्षेत्र को नहीं, वर्ग की आवृत्ति को संदर्भित करता है।
सेस टिम्मरमैन

10

यह पायथन ज़ेन का पालन करने के लिए है "स्पष्ट रूप से निहित से बेहतर है"। यह वास्तव में आपकी कक्षा वस्तु का संदर्भ है। उदाहरण के लिए, जावा और PHP में, इसे कहा जाता है this

यदि user_type_nameआपके मॉडल पर एक फ़ील्ड है जिसे आप इसके द्वारा एक्सेस करते हैं self.user_type_name


10

सबसे पहले, स्व एक पारंपरिक नाम है, आप इसके स्थान पर कुछ और (सुसंगत होने के नाते) रख सकते हैं।

यह स्वयं ऑब्जेक्ट को संदर्भित करता है, इसलिए जब आप इसका उपयोग कर रहे हैं, तो आप घोषणा कर रहे हैं कि .name और .age छात्र ऑब्जेक्ट्स के गुण हैं (ध्यान दें, छात्र वर्ग का नहीं) जो आप बनाने जा रहे हैं।

class Student:
    #called each time you create a new Student instance
    def __init__(self,name,age): #special method to initialize
        self.name=name
        self.age=age

    def __str__(self): #special method called for example when you use print
        return "Student %s is %s years old" %(self.name,self.age)

    def call(self, msg): #silly example for custom method
        return ("Hey, %s! "+msg) %self.name

#initializing two instances of the student class
bob=Student("Bob",20)
alice=Student("Alice",19)

#using them
print bob.name
print bob.age
print alice #this one only works if you define the __str__ method
print alice.call("Come here!") #notice you don't put a value for self

#you can modify attributes, like when alice ages
alice.age=20
print alice

कोड यहाँ है


1
आपका उत्तर मुझे सबसे स्पष्ट लगता है। +1
पावेल

9

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


8

तर्क का उपयोग, पारंपरिक रूप से कहा जाता selfहै समझने में उतना कठिन नहीं है, क्योंकि यह आवश्यक क्यों है? या क्यों स्पष्ट रूप से इसका उल्लेख करने के लिए? मेरा मानना ​​है कि अधिकांश उपयोगकर्ताओं के लिए यह एक बड़ा सवाल है, जो इस प्रश्न को देखते हैं, या यदि यह नहीं है, तो निश्चित रूप से उनके पास एक ही प्रश्न होगा क्योंकि वे सीखने के अजगर को आगे बढ़ाते हैं। मैं उन्हें इन दोहों को पढ़ने की सलाह देता हूं:

1: समझाया गया स्व का उपयोग

ध्यान दें कि यह एक कीवर्ड नहीं है।

हर वर्ग विधि का पहला तर्क, जिसमें init शामिल है, हमेशा कक्षा की वर्तमान आवृत्ति का संदर्भ है। अधिवेशन द्वारा, इस तर्क को हमेशा स्वयं नाम दिया जाता है। Init विधि में, आत्म नव निर्मित वस्तु को संदर्भित करता है; अन्य कक्षा विधियों में, यह उस उदाहरण को संदर्भित करता है जिसकी विधि को कहा जाता था। उदाहरण के लिए नीचे का कोड उपरोक्त कोड के समान है।

2: हमारे पास ऐसा क्यों है और हम जावा की तरह एक तर्क के रूप में इसे समाप्त क्यों नहीं कर सकते हैं और इसके बजाय एक कीवर्ड है

एक और बात जो मैं जोड़ना चाहूंगा, एक वैकल्पिक selfतर्क मुझे लिखने के द्वारा किसी वर्ग के अंदर स्थिर तरीकों की घोषणा करने की अनुमति देता है self

कोड उदाहरण:

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

    def objectMethod(self):
        print "This is an object method which needs an instance of a class, and that is what self refers to"

पुनश्च : यह केवल पायथन 3.x में काम करता है।

पिछले संस्करणों में, आपको स्पष्ट रूप से @staticmethodडेकोरेटर जोड़ना होगा , अन्यथा selfतर्क अनिवार्य है।


7

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


6

निम्नलिखित उदाहरण पर एक नज़र डालें, जो स्पष्ट रूप से इसका उद्देश्य बताता है self

class Restaurant(object):  
    bankrupt = False

    def open_branch(self):
        if not self.bankrupt:
           print("branch opened")

#create instance1
>>> x = Restaurant()
>>> x.bankrupt
False

#create instance2
>>> y = Restaurant()
>>> y.bankrupt = True   
>>> y.bankrupt
True

>>> x.bankrupt
False  

self उदाहरणों के बीच अंतर करने के लिए उपयोग / आवश्यक है।

स्रोत: अजगर में स्व चर को समझाया गया - पायथन


हां, मुझे लगता है कि हम जानते हैं कि स्वयं का उपयोग क्यों किया जाता है, लेकिन सवाल यह है कि भाषा आपको स्पष्ट रूप से घोषित क्यों करती है। कई अन्य भाषाओं को इसकी आवश्यकता नहीं होती है और एक ऐसी भाषा जो संक्षिप्त होने पर गर्व करती है, आपको लगता है कि वे आपको लुआ या सी ++ (यह) का उपयोग करने के लिए पर्दे के पीछे चर देंगे।
user441521

3
@ kmario23 आप यहाँ से प्रतिक्रिया कर रहे हैं: pythontips.com/2013/08/07/the-self-variable-in-python-explained कृपया हमेशा मूल लेखकों को स्वीकार करें जब अपने स्वयं के रूप में उत्तर पोस्ट करें।
geekidharsh

@geekidharsh धन्यवाद, मैंने एक नोट जोड़ा!
kmario23

5

क्या इसलिए कि जिस तरह से अजगर को डिजाइन किया गया है वैसा विकल्प शायद ही काम करेगा। पायथन को उन तरीकों या कार्यों की अनुमति देने के लिए डिज़ाइन किया गया है, जिन्हें एक संदर्भ में परिभाषित किया जाता है, जहाँ दोनों this(a-la Java / C ++) या स्पष्ट @(a-la ruby) काम नहीं करेंगे। आइए अजगर सम्मोहन के साथ स्पष्ट दृष्टिकोण के साथ एक उदाहरण दें:

def fubar(x):
    self.x = x

class C:
    frob = fubar

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

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

def fubar(x)
    myX = x

class C:
    frob = fubar

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

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

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

 class C:
     frob = fubar

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


3

में __init__ विधि, आत्म नव निर्मित वस्तु को संदर्भित करता है; अन्य कक्षा विधियों में, यह उस उदाहरण को संदर्भित करता है जिसकी विधि को कहा जाता था।

स्व, एक नाम के रूप में, सिर्फ एक सम्मेलन है , इसे आप चाहते हैं के रूप में कहते हैं! लेकिन इसका उपयोग करते समय, उदाहरण के लिए, ऑब्जेक्ट को हटाने के लिए, आपको उसी नाम का उपयोग करना होगा: __del__(var)जहां varउपयोग किया गया था__init__(var,[...])

आप clsभी देख लेना चाहिए , बड़ी तस्वीर है । यह पोस्ट मददगार हो सकती है।


3

स्वयं वर्तमान वस्तु के नाम या वर्ग के उदाहरण की तरह काम कर रहा है।

# Self explanation.


 class classname(object):

    def __init__(self,name):

        self.name=name
        # Self is acting as a replacement of object name.
        #self.name=object1.name

   def display(self):
      print("Name of the person is :",self.name)
      print("object name:",object1.name)


 object1=classname("Bucky")
 object2=classname("ford")

 object1.display()
 object2.display()

###### Output 
Name of the person is : Bucky
object name: Bucky
Name of the person is : ford
object name: Bucky

1

self अपरिहार्य है।

बस एक प्रश्नself निहित या स्पष्ट होना चाहिए था । Guido van Rossumइस सवाल को हल करते हुए कहा कि selfरहना है

तो कहाँ selfरहते हैं?

अगर हम सिर्फ कार्यात्मक प्रोग्रामिंग से चिपके रहेंगे तो हमें ज़रूरत नहीं होगी self। एक बार जब हम पायथन ओओपी में प्रवेश करते हैं तो हम पाते हैंself तो वहां हैं।

यहां class Cविधि के साथ विशिष्ट उपयोग का मामला हैm1

class C:
    def m1(self, arg):
        print(self, ' inside')
        pass

ci =C()
print(ci, ' outside')
ci.m1(None)
print(hex(id(ci))) # hex memory address

यह कार्यक्रम आउटपुट देगा:

<__main__.C object at 0x000002B9D79C6CC0>  outside
<__main__.C object at 0x000002B9D79C6CC0>  inside
0x2b9d79c6cc0

तो selfवर्ग उदाहरण का मेमोरी पता रखता है। उद्देश्य के selfलिए संदर्भ धारण करने के लिए किया जाएगा उदाहरण के तरीकों और हमें करने के लिए के लिए स्पष्ट है कि संदर्भ के लिए उपयोग।


नोट तीन अलग-अलग प्रकार के वर्ग तरीके हैं:

  • स्थिर विधियाँ (पढ़ें: कार्य),
  • कक्षा के तरीके,
  • उदाहरण के तरीके (उल्लेख)।

0

से डॉक्स ,

विधियों के बारे में विशेष बात यह है कि उदाहरण ऑब्जेक्ट फ़ंक्शन के पहले तर्क के रूप में पारित किया जाता है। हमारे उदाहरण में, कॉल x.f()बिल्कुल बराबर है MyClass.f(x)। सामान्य तौर पर, n तर्कों की सूची के साथ एक विधि को कॉल करना तर्कों के साथ संबंधित फ़ंक्शन को कॉल करने के बराबर है, जो पहले तर्क से पहले विधि के उदाहरण ऑब्जेक्ट को सम्मिलित करके बनाया गया है।

संबंधित स्निपेट से पहले,

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

x = MyClass()


-2

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


21
मुझे नहीं लगता कि इससे रिचजिला को इसके पीछे के कारण को समझने में मदद मिलती है।
जॉर्ज स्कोली 20

1
@SilentGhost: आपने इसे रद्द कर दिया है। मैं प्रभावित हु। अगर मैं इसे सही ढंग से समझता हूं: मैं एक ऑब्जेक्ट को परिभाषित वर्ग के उदाहरण के रूप में बनाता हूं और स्व पैरामीटर उस ऑब्जेक्ट को संदर्भित करता है? मैं समझता हूं कि स्व का तात्पर्य कक्षा में निहित तरीके से है, लेकिन यह बहुत अच्छा होगा यदि आप अपने उत्तर को थोड़ा और समझाएं।
dkrynicki 14
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.