2012-11-01 20 views
8

: kendisi için referans gereken yinelemeli fonksiyonu olarakstaticmethod ve özyineleme? Kod şu var

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

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

çubuğu(). Ancak, bar() bir sınıfın içinde ve return bar(n-1) numaralı çağrı, NameError: global name 'bar' is not defined çağrılırken çalışmaz. Böyle bir durumla nasıl baş edebilirim? Çubuğu() bir sınıf veya örnek yöntemine değiştirmem gerekirse, self veya cls'a erişime izin vermeli miyim?

+1

Özyinelemeli çağrıda Foo.bar (n-1) 'yi çağırıyor mu? – inspectorG4dget

cevap

4

işlevine referans tutmak için bir kapağın kullanılmasına bir sınıf yöntemi kullanılarak ya da (diğerleri tarafından gösterildiği gibi) adıyla sınıf çağrı için bir alternatif:

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

(küçük) avantajı, isimler değiştiğinde bu durumun kırılmaya daha az duyarlı olmasıdır. Örneğin,bar içinde Foo.bariçin bir başvuru varsa, bu bar tanımlandığı sınıf için genel bir ad olmaya devam eden Foo dayanır. Genellikle bu durum böyle değil, ancak, özyinelemeli çağrı sonları.

classmethod yaklaşımı, yönteme sınıfla ilgili bir başvuruda bulunacaktır, ancak sınıf, yöntemin aksi belirtilmedikçe yönteme başka şekilde gerek duyulmaz. Kapatma kullanımı da, her aramanın bir öznitelik araması yapmadığından, marjinal olarak daha hızlı olacaktır.

16

Sen sınıf adı önüne işaret koyun bar başvurabilirsiniz:

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) 

Statik yöntemler sonuçta bir sınıfın İsim alanları içinde düzenli fonksiyonları başka bir şey değildir.

Seçenek olarak ise, normal bir fonksiyonu olarak bar tanımlar: tamamen bütün sorunu önler

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

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

.

+0

@senderle: evet, sadece benim bölümümde bir c & p hatası var. Python 3'te de buna ihtiyacın var. –

+0

Aslında, kod Python 3'te düzgün şekilde çalışıyor - en azından Foo'nun kendisinden arandığında. (Ama bir Foo 'örneğinden çağrıldığında işe yaramadığını görüyorum.) – senderle

+3

Senderle Python 3'te çalışıyor çünkü aramada' isinstance (self, DefiningClass) 'gerektiren bir" bağlanmamış "yöntem yok. yöntemleri. Sadece 'staticmethod' ile çalışan bir şey, yöntemi bir örnekte çağırır ('Foo(). Bar (1)'). – delnan

7

Buna ne dersiniz?

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

Foo'nun dışındaki çubuğu() tanımlayabilir ve daha sonra onu statik yöntem olarak getirebilir, böylece sınıfın bir yöntemi olarak sınıfının tüm faydalarını elde edemezsiniz ve bu da sınıfı kendisine göndermeye gerek kalmaz. Sınıf mirası nedenleriyle böyle bir şeye ihtiyacım vardı.

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)