मैं पायथन में वर्ग विधियों के भीतर "स्थिर" वर्ग चर कैसे एक्सेस कर सकता हूं?


162

यदि मेरे पास निम्न अजगर कोड है:

class Foo(object):
    bar = 1

    def bah(self):
        print(bar)

f = Foo()
f.bah()

इसकी शिकायत है

NameError: global name 'bar' is not defined

मैं barविधि के भीतर वर्ग / स्थिर चर का उपयोग कैसे कर सकता हूं bah?


पाइथन और स्टैटिक्स के बारे में अधिक जानकारी यहाँ पाई जा सकती है: stackoverflow.com/questions/68645/python-static-variable
शयनकक्ष

जवाबों:


166

इसके बजाय barउपयोग self.barया Foo.barFoo.barएक स्थिर चर बनाने के लिए असाइन करना , और self.barएक उदाहरण चर बनाने के लिए असाइन करना होगा।


12
Foo.bar काम करेगा, लेकिन self.bar एक उदाहरण चर बनाता है, एक स्थिर नहीं।
शयन कक्ष

47
bedwyr, "print self.bar" कोई उदाहरण चर नहीं बनाएगा (हालांकि सेल्फ स्वबार को असाइन करना होगा)।
कांस्टेंटिन

@ कॉन्स्टेंटिन - मुझे यह महसूस नहीं हुआ कि यह एक दिलचस्प अंतर है। सुधार के लिए धन्यवाद :-)
bedwyr

2
लेकिन अगर आप वहां आइवर होने का इरादा नहीं रखते हैं, तो Foo.classmember का उपयोग करने के लिए इसका क्लीयर है।
mk12

2
स्थैतिक चर का उपयोग करते समय, यहाँ से गोच को पढ़ना एक अच्छा विचार है: stackoverflow.com/questions/68645/… । @ कॉन्स्टेंटिन कई गोचरों में से एक देता है।
ट्रेवर बॉयड स्मिथ

84

वर्ग विधि को परिभाषित करें:

class Foo(object):
    bar = 1
    @classmethod
    def bah(cls):    
        print cls.bar

अब अगर bah()इंस्टेंस मेथड (यानी सेल्फ की एक्सेस) हो तो भी आप सीधे क्लास वेरिएबल को एक्सेस कर सकते हैं।

class Foo(object):
    bar = 1
    def bah(self):    
        print self.bar

3
केवल स्व.__क्लास__.बार के बजाय फू.बार ही क्यों?
mk12 20

15
@ Mk12: जब आपको क्लास इनहेरिटेंस मिली है, एक "क्लास वेरिएबल" बेस क्लास या सबक्लास में हो सकता है। आप किसका उल्लेख करना चाहते हैं? आप क्या करने की कोशिश कर रहे हैं पर निर्भर करता है। Foo.bar हमेशा निर्दिष्ट वर्ग की एक विशेषता को संदर्भित करेगा - जो एक आधार वर्ग या उपवर्ग हो सकता है। self.__class__.bar को संदर्भित करता है जो भी वर्ग एक प्रकार का उदाहरण है।
क्रेग मैकक्यून

7
अब हम उस दुर्भाग्यपूर्ण बिंदु पर पहुंच गए हैं, जब हम भाषा के विवरणों के बारे में इतने जागरूक हो जाते हैं कि हम दो बारीक रूप से उपयोग किए गए मामलों के बीच भेदभाव कर सकते हैं। यह वास्तव में निर्भर करता है कि आप क्या करना चाहते हैं, लेकिन कई लोग ऐसी सूक्ष्मताओं में शामिल नहीं होंगे।
होल्डनवेब

2
BTW, यह "वर्ग चर" का दुर्लभ उपयोग है। यह एक विशेष वर्ग में परिभाषित करने के लिए बहुत अधिक सामान्य है, यहाँ फू। यह कुछ उन्नत प्रोग्रामिंग स्थितियों के लिए उपयोगी जानकारी है। लेकिन लगभग निश्चित रूप से नहीं कि मूल प्रश्न एक उत्तर के रूप में क्या चाहता था (किसी को भी, जिसे इस उत्तर की आवश्यकता है, पहले से ही जानता होगा कि Foo.bar कैसे करना है)। +1 क्योंकि मैंने इससे कुछ सीखा है।
टूलमेकरसेव

3
कक्षा चर और विधियों का उपयोग कब करना है (उदाहरण के लिए चर और विधियों के विपरीत) मैं सीख रहा हूं। जब आप किसी श्रेणी चर को आवृत्ति विधि से एक्सेस करना चाहते हैं, तो क्या self.__class__.bar का उपयोग करना आवश्यक है? मैंने देखा कि स्व.बार काम करता है जबकि बार एक वर्ग चर है उदाहरण आवृत्ति नहीं।
बिल

13

सभी अच्छे उदाहरणों के साथ, आपने सरल कर दिया है कि आप वास्तव में क्या करने की कोशिश कर रहे हैं। यह अच्छा है, लेकिन यह ध्यान देने योग्य है कि जब कक्षा बनाम उदाहरण चर की बात आती है तो अजगर में बहुत लचीलापन होता है। वही विधियों के बारे में कहा जा सकता है। संभावनाओं की एक अच्छी सूची के लिए, मैं माइकल फॉक्स की नई शैली की कक्षाओं के परिचय को पढ़ने की सलाह देता हूं , विशेष रूप से खंड 6 से 6।

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

अजगर के साथ, अंगूठे का भव्य नियम यह है कि तीन नामस्थान हैं जिन्हें खोजा जाता है, क्रम में, चर के लिए:

  1. कार्य / विधि
  2. वर्तमान मॉड्यूल
  3. Builtins

{begin pedagogy}

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

>>> class A(object):
        foo = 'foo'
        bar = foo


>>> A.foo
'foo'
>>> A.bar
'foo'

परंतु:

>>> class B(object):
        foo = 'foo'
        def get_foo():
            return foo
        bar = get_foo()



Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    class B(object):
  File "<pyshell#11>", line 5, in B
    bar = get_foo()
  File "<pyshell#11>", line 4, in get_foo
    return foo
NameError: global name 'foo' is not defined

{end pedagogy}

अंत में, याद रखने वाली बात यह है कि आपके पास उन किसी भी वैरिएबल तक पहुंच है, जिसे आप एक्सेस करना चाहते हैं, लेकिन संभवतः नहीं। यदि आपके लक्ष्य सरल और सीधे हैं, तो Foo.bar या self.bar के लिए जाना संभवतः पर्याप्त होगा। यदि आपका उदाहरण अधिक जटिल हो रहा है, या आप वंशानुक्रम जैसी फैंसी चीजें करना चाहते हैं (आप स्थैतिक / वर्ग विधियों को विरासत में प्राप्त कर सकते हैं!), या कक्षा के भीतर अपनी कक्षा के नाम का जिक्र करने का विचार ही आपको गलत लगता है, तो देखें। परिचय मैं जुड़ा हुआ


IIRC, इसमें तकनीकी रूप से 3 (+) नाम स्थान खोजे गए हैं - फ़ंक्शन-लोकल, मॉड्यूल / ग्लोबल और बिल्डिंस। नेस्टेड स्कोप का मतलब है कि कई स्थानीय स्कोप खोजे जा सकते हैं, लेकिन यह असाधारण मामलों में से एक है। (...)
जेफ शैनन

इसके अलावा, मैं 'मुख्य मॉड्यूल' कहने में सावधान रहूंगा, क्योंकि यह फ़ंक्शन का मॉड्यूल है जिसे खोजा गया है, मुख्य मॉड्यूल नहीं ... और उदाहरण रेफरी से विशेषता को देखना एक अलग बात है, लेकिन यह उत्तर बताता है कि क्यों आपको उदाहरण / वर्ग रेफरी की आवश्यकता है।
जेफ शैनन


-2
class Foo(object):    
    bar = 1

    def bah(object_reference):
        object_reference.var = Foo.bar
        return object_reference.var


f = Foo() 
print 'var=', f.bah()

4
हालांकि यह कोड प्रश्न को हल कर सकता है, जिसमें यह भी बताया गया है कि यह समस्या कैसे और क्यों हल करती है, इससे वास्तव में आपके पोस्ट की गुणवत्ता को बेहतर बनाने में मदद मिलेगी, और संभवत: अधिक वोट मिले। याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, न कि केवल उस व्यक्ति से जो अब पूछ रहा है। स्पष्टीकरण जोड़ने के लिए कृपया अपना उत्तर संपादित करें और संकेत दें कि क्या सीमाएँ और मान्यताएँ लागू होती हैं। समीक्षा से
डबल-बीप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.