staticmethod和递归?

时间:2012-11-01 18:42:22

标签: python class methods

我有以下代码:

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吗?

5 个答案:

答案 0 :(得分:25)

您可以通过在其前面加上类名称来引用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)

完全避免了整个问题。

答案 1 :(得分: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 :(得分:5)

使用类方法或按名称调用类(如其他人所示)的替代方法是使用闭包来保存对函数的引用:

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 ,则依赖Foo继续作为{{1}的类的全局名称通常就是这种情况,但如果不是这样,那么递归调用会中断。

bar方法将为该方法提供对类的引用,但该方法中不需要该类,这似乎是不优雅的。使用闭包也会略微加快,因为它没有在每次调用时进行属性查找。

答案 3 :(得分: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)

答案 4 :(得分:0)

如果主要目标是运行递归方法,您可以为此使用普通方法。

实际上直到现在我才看到它的用途。假设您有需要测试的整数阈值,这种模式非常好且简单:(即使它可能会造成一些过热,所以要小心)

class Foo(object):

    def __init__(self, n):
        self.baz = self.bar(n)

    def bar(self, n):
        if n < -10:
            return 'bar < -10'
        if n == -10:
            return 'bar -10 - -1'
        if n == 0:
            return 'bar 0 - 9'
        if n == 10:
            return 'bar 10 - 19'
        if n >= 20:
            return 'bar >= 20'
        return self.bar(n-1)