2012-11-01 5 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) 

바(). 그러나 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의 참조가있는 경우이 값은 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 : 예, 내 부분에 C & P 오류가 있습니다. 파이썬 3에서도 필요합니다. –

+0

실제로 코드는 파이썬 3에서는 제대로 실행되지 않습니다. - 적어도'Foo'에서 호출되었을 때. (하지만'Foo' 인스턴스에서 호출했을 때 작동하지 않는다는 것을 알 수 있습니다.) – senderle

+3

@senderle 파이썬 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()를 정의한 다음 staticmethod로 가져 와서 클래스의 메소드가되는 이점을 모두 얻도록 할 수 있으며 클래스를 닫거나 클래스 자체를 참조하지 않아도됩니다. 클래스 상속 이유로 이런 것이 필요했습니다.

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)