2012-11-01 49 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()的,因为它需要本身参考递归函数。但是,bar()在类中,调用return bar(n-1)将不起作用,调用NameError: global name 'bar' is not defined。我该如何处理这种情况?我是否应该将bar()更改为类或实例方法,从而允许访问selfcls

+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

@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)