2010-01-09 8 views
14

एक रिकर्सिव फ़ंक्शन के लिए हम कर सकते हैं:पायथन: कक्षा के भीतर से इसका संदर्भ कैसे लें (रिकर्सिव फ़ंक्शन की तरह)

def f(i): 
    if i<0: return 
    print i 
    f(i-1) 

f(10) 

हालांकि क्या निम्न कार्य करने का कोई तरीका है?

class A: 
    # do something 
    some_func(A) 
    # ... 
+1

स्पष्ट नहीं है कि आप क्या चाहते हैं या मतलब है। 'कक्षा ए:' कोई ऑब्जेक्ट नहीं बनाता है, इसलिए संदर्भ में कोई 'ए' नहीं है। संभावित चीजों के लिए प्रस्तुत समाधान देखें ... –

+8

@Andrew __class ए: __ एक _class object_ बनाता है क्योंकि पाइथन में कक्षाएं प्रथम श्रेणी –

उत्तर

4

आप एक ही वस्तु का उल्लेख करना चाहते हैं, तो बस 'स्वयं' का उपयोग करें:

class A: 
    def some_func(self): 
     another_func(self) 

आप एक ही कक्षा की एक नई वस्तु बनाने के लिए चाहते हैं, बस कर:

class A: 
    def some_func(self): 
     foo = A() 

आप metaclass वर्ग वस्तु का उपयोग (सबसे अधिक संभावना है कि तुम क्या नहीं करना चाहता) करना चाहते हैं, फिर से, बस कर:

class A: 
    def some_func(self): 
     another_func(A) # note that it reads A, not A() 
+2

बस एक स्पष्टीकरण: आपके अंतिम उदाहरण में, "ए" का जिक्र करने के रूप में जाना जाता है "क्लास ऑब्जेक्ट", "मेटाक्लास" नहीं, जो एक पूरी तरह से अलग अवधारणा है। आपके उदाहरण में ए का मेटाक्लास 'प्रकार' होगा।क्लासटाइप '(या' टाइप' 'यदि नए स्टाइल क्लासेस या पायथन 3 का उपयोग करते हैं) – Crast

-1

कक्षा में अधिकांश कोड विधि परिभाषाओं के अंदर होंगे, इस मामले में आप आसानी से A नाम का उपयोग कर सकते हैं।

+1

-1 वह कक्षा के मुख्य निकाय में ए को कॉल करने के बारे में बहुत विशेष रूप से पूछ रहा है, न कि इसकी विधियों से। –

0

आप क्या हासिल करना चाहते हैं? एक मेटाक्लास का उपयोग करके अपनी परिभाषा को ट्विक करने के लिए कक्षा तक पहुंच बनाना संभव है, लेकिन इसकी अनुशंसा नहीं की जाती है।

आपका कोड नमूना बस के रूप में लिखा जा सकता है:

class A(object): 
    pass 
some_func(A) 
1

वहाँ उस वर्ग दायरे के भीतर, जब तक एक कुछ और पहली (और फिर some_func होने के लिए परिभाषित किया गया था करने के लिए एक तरीका नहीं है (ए) आप जो अपेक्षा करते हैं उससे पूरी तरह से कुछ अलग करेंगे)

जब तक आप वर्ग में बिट्स जोड़ने के लिए कुछ प्रकार के स्टैक निरीक्षण नहीं कर रहे हैं, तो ऐसा लगता है कि आप ऐसा क्यों करना चाहते हैं। क्यों नहीं:

class A: 
    # do something 
    pass 

some_func(A) 

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

0

नहीं। यह फ़ंक्शन में काम करता है क्योंकि फ़ंक्शन सामग्री कॉल-टाइम पर निष्पादित की जाती है। लेकिन वर्ग सामग्री को परिभाषित समय पर निष्पादित किया जाता है, जिस बिंदु पर कक्षा अभी तक मौजूद नहीं है।

यह नहीं सामान्य रूप से एक समस्या है क्योंकि आप इसे परिभाषित करने के बाद कक्षा में आगे सदस्यों को हैक कर सकते हैं, तो आप कई भागों में एक वर्ग परिभाषा अलग कर सकते हैं:

class A(object): 
    spam= 1 

some_func(A) 

A.eggs= 2 

def _A_scramble(self): 
    self.spam=self.eggs= 0 
A.scramble= _A_scramble 

हालाँकि इस बात पर बहुत असामान्य चाहते है कक्षा में अपनी परिभाषा के बीच में एक समारोह को कॉल करने के लिए। यह स्पष्ट नहीं है कि आप क्या करने का प्रयास कर रहे हैं, लेकिन संभावना है कि आप decorators (या अपेक्षाकृत नए class decorators) के साथ बेहतर होंगे।

0

यदि यह वास्तव में दायरे में है तो यह उसके शरीर के अंदर कक्षा के नाम (जैसे विधि परिभाषाओं की तरह) का संदर्भ देना ठीक है ... यदि यह शीर्ष स्तर पर परिभाषित किया गया है तो यह होगा। (शायद अन्य मामलों में, पाइथन स्कॉइंग क्विर्क के कारण नहीं!)।

scoping पकड़ लिया संख्या का चित्रण पर के लिए, फू का दृष्टांत का प्रयास करें:


इसके अलावा

class Foo(object): 
    class Bar(object): 
     def __init__(self): 
      self.baz = Bar.baz 
     baz = 15 
    def __init__(self): 
     self.bar = Foo.Bar() 

(। यह वैश्विक नाम 'बार' नहीं परिभाषित किया जा रहा बारे में शिकायत करने जा रहा है), कुछ मुझे बताता है कि आप कक्षा विधियों में देखना चाहते हैं: docs on the classmethod function (सजावट के रूप में उपयोग करने के लिए), a relevant SO questionसंपादित करें: ठीक है, तो यह सुझाव बिल्कुल उचित नहीं हो सकता है ... यह सिर्फ इतना है कि मैंने आपके प्रश्न को पढ़ने के बारे में सोचा था, वैकल्पिक कन्स्ट्रक्टर इत्यादि जैसी चीजें थीं। अगर आपकी आवश्यकताओं के अनुरूप कुछ आसान है, तो @classmethod अजीबता को साफ़ करें । :-)

5

आप उस विशिष्ट वाक्यविन्यास के साथ नहीं कर सकते जिसके बारे में आप वर्णन कर रहे हैं, जिस समय उनका मूल्यांकन किया जाता है। फ़ंक्शन बॉडी के उदाहरण के कारण f (i-1) पर कॉल का कारण यह है कि f का नाम समाधान तब तक नहीं किया जाता जब तक फ़ंक्शन वास्तव में नहीं कहा जाता है। इस बिंदु पर एफ निष्पादन के दायरे में मौजूद है क्योंकि फ़ंक्शन का मूल्यांकन पहले से ही किया जा चुका है। कक्षा के उदाहरण के मामले में, कक्षा के नाम का संदर्भ तब देखा जाता है जब कक्षा परिभाषा का अभी भी मूल्यांकन किया जा रहा है। इस प्रकार, यह अभी तक स्थानीय दायरे में मौजूद नहीं है।

वैकल्पिक रूप से, वांछित व्यवहार इस तरह की तरह एक metaclass का उपयोग कर पूरा किया जा सकता:

class MetaA(type): 

    def __init__(cls): 
     some_func(cls) 

class A(object): 
    __metaclass__=MetaA 
    # do something 
    # ... 

इस दृष्टिकोण का उपयोग करके आप समय है कि वर्ग मूल्यांकन किया जाता है पर वर्ग वस्तु पर मनमाने ढंग से संचालन कर सकते हैं।

+1

यह एकमात्र उत्तर है जो बताता है * क्यों * यह नहीं किया जा सकता है (कार्य निकायों को परिभाषा पर ही निष्पादित नहीं किया जाता है, जबकि कक्षा निकाय होते हैं)। स्पष्टीकरण के लिए धन्यवाद। – Dubslow

1

तुम सिर्फ एक छोटे से hacky बात करना चाहते हैं तो

class A(object): 
    ... 
some_func(A) 

करना चाहते हैं कि कोई metaclass उपयोग कर सकते हैं और अधिक परिष्कृत कुछ करना चाहते हैं। क्लास ऑब्जेक्ट को पूरी तरह से बनाए जाने से पहले एक मेटाक्लास जिम्मेदार होता है। एक टेम्पलेट होगा:

class AType(type): 
    def __new__(meta, name, bases, dct): 
     cls = super(AType, meta).__new__(meta, name, bases, dct) 
     some_func(cls) 
     return cls 

class A(object): 
    __metaclass__ = AType 
    ... 

type डिफ़ॉल्ट metaclass है। मेटाक्लास के उदाहरण कक्षाएं हैं इसलिए __new__A का एक संशोधित उदाहरण लौटाता है।

मेटाक्लास पर अधिक के लिए, http://docs.python.org/reference/datamodel.html#customizing-class-creation देखें।

14

पायथन में आप कक्षा के शरीर में कक्षा का संदर्भ नहीं दे सकते हैं, हालांकि रूबी जैसी भाषाओं में आप इसे कर सकते हैं।

पाइथन में इसके बजाय आप एक कक्षा सजावट का उपयोग कर सकते हैं लेकिन कक्षा शुरू होने के बाद इसे बुलाया जाएगा। एक और तरीका मेटाक्लास का उपयोग करना हो सकता है लेकिन यह उस पर निर्भर करता है जिसे आप प्राप्त करने की कोशिश कर रहे हैं।

+0

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

+0

यह प्राप्त करने के लिए आप कक्षा सजावट और मेटाक्लास का उपयोग कैसे करते हैं? एक उदाहरण बहुत अच्छा होगा। –

संबंधित मुद्दे