2012-11-01 15 views
8

मैं कोड निम्नलिखित है:staticmethod और रिकर्सन?

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

    @staticmethod 
    def bar(n): 
     if n==0: 
      return 'bar' 
     else: 
      return bar(n-1) 

बार() एक पुनरावर्ती समारोह वह खुद के संदर्भ में की जरूरत के रूप में। हालांकि, बार() एक कक्षा के अंदर है, और return bar(n-1) पर कॉल नहीं करेगा, NameError: global name 'bar' is not defined का आह्वान करेगा। मैं इस तरह की स्थिति से कैसे निपट सकता हूं? क्या मुझे बार() को कक्षा या उदाहरण विधि में बदलना चाहिए, जिससे self या cls तक पहुंच की अनुमति मिलती है?

+1

रिकर्सिव कॉल सहायता में 'Foo.bar (n-1)' को कॉल करना क्या मदद करता है? – inspectorG4dget

उत्तर

4

एक वर्ग पद्धति का उपयोग करके या नाम (के रूप में दूसरों के द्वारा दिखाया गया है) द्वारा वर्ग बुला रहा है एक बंद उपयोग करने के लिए कार्य करने के लिए संदर्भ धारण करने के लिए के लिए एक वैकल्पिक:

class Foo(object): 
    def bar(): 
     def bar(n): 
      if n == 0: 
       return "bar" 
      return bar(n-1) 
     return bar 
    bar = staticmethod(bar()) 

(मामूली) लाभ यह है कि जब नाम बदलते हैं तो यह तोड़ने के लिए कुछ हद तक कम संवेदनशील होता है। उदाहरण के लिए, यदि आपbar अंदर Foo.barके लिए एक संदर्भ है, यह Foo वर्ग कि bar में परिभाषित किया गया है के लिए एक वैश्विक नाम होने के लिए जारी पर निर्भर करता है। आम तौर पर यह मामला है लेकिन अगर यह तो पुनरावर्ती कॉल नहीं, है टूट जाता है।

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

16

आप वर्ग के नाम के साथ इसे लगाकर द्वारा bar का उल्लेख कर सकते हैं:

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

    @staticmethod 
    def bar(n): 
     if n==0: 
      return 'bar' 
     else: 
      return Foo.bar(n-1) 

स्टेटिक तरीकों लेकिन सब के बाद एक वर्ग के नाम स्थान के भीतर निहित नियमित कार्यों में कुछ भी नहीं कर रहे हैं।

वैकल्पिक रूप से, बजाय एक नियमित रूप से समारोह के रूप में bar को परिभाषित:

def bar(n): 
    if n==0: 
     return 'bar' 
    else: 
     return bar(n-1) 

class Foo(object): 
    def __init__(self): 
     baz=bar(10) 

जो पूरे मुद्दे को पूरी तरह से बचा जाता है।

+0

@sendle: हाँ, मेरे हिस्से पर सिर्फ एक सी और पी त्रुटि। आपको इसे पायथन 3 में भी चाहिए। –

+0

असल में कोड पाइथन 3 में इसके बिना सही ढंग से चलता है - कम से कम जब 'फू' से बुलाया जाता है। (लेकिन मुझे लगता है कि यह 'फू' इंस्टेंस से कॉल होने पर काम नहीं करता है।) – senderle

+3

@sendle यह पायथन 3 में काम करता है क्योंकि अब "अनबाउंड विधि" रैपर नहीं हैं जिन्हें कॉल करने पर 'इंस्टेंसेंस (सेल्फ, डेफिनिंग क्लास)' की आवश्यकता होती है तरीकों। एक चीज जो केवल '@ staticmethod' के साथ काम करती है, विधि को विधि (' Foo()। Bar (1) ') पर कॉल कर रही है। – delnan

7

इसके बारे में क्या?

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

    @classmethod 
    def bar(cls, n): 
     if n == 0: 
      return 'bar' 
     else: 
      return cls.bar(n-1) 
2

आप फू के बाहर बार() को परिभाषित कर सकते हैं और फिर इसे एक स्थिर विधि के रूप में ला सकते हैं ताकि आप इसे बंद करने या वर्ग को संदर्भित करने के दौरान कक्षा के तरीके के सभी लाभ प्राप्त कर सकें। कक्षा विरासत कारणों के लिए मुझे इस तरह कुछ चाहिए।

def bar(n): 
    if n==0: 
     return 'bar' 
    else: 
     return bar(n-1) 

class Foo(object): 
    bar = staticmethod(bar) 
    def __init__(self): 
     baz=self.bar(10) 
संबंधित मुद्दे