2012-11-01 9 views
8

:それは自分自身への参照を必要とする再帰関数として静的メソッドと再帰?私は次のコードしている

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

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

バー()。ただし、bar()はクラス内にあり、return bar(n-1)を呼び出すと機能しません。NameError: global name 'bar' is not definedを呼び出します。このような状況にどう対処することができますか? bar()をクラスまたはインスタンスメソッドに変更すると、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()) 

(マイナー)利点は、名前が変更されたときにこれがやや壊れにくいことです。たとえば、Foo.barの中に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

@senderle:ええ、私のところではC&Pエラーです。 Python 3でも必要です。 –

+0

実際には、コードはPython 3では正しく動作しません。少なくとも、 'Foo'自身から呼び出されたときは。 (しかし、 'Foo'インスタンスから呼び出されたときに動作しないことが分かります) – senderle

+3

@senderle Python 3では、呼び出し時に' isinstance(self、DefiningClass) 'を必要とする"バインドされていないメソッド "メソッド。 '@ 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

Fooの外側でbar()を定義し、静的メソッドとして呼び出すことで、クラスのメソッドであるという利点をすべて得ることができます。ただし、クラス自体を閉じたりクラス自体を参照したりする必要はありません。私はクラスの継承の理由から、このようなものが必要でした。

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) 
関連する問題