staticmethod和递归?

thk*_*ang 13 python methods class

我有以下代码:

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

    @staticmethod
    def bar(n):
        if n==0:
            return 'bar'
        else:
            return bar(n-1)
Run Code Online (Sandbox Code Playgroud)

bar()作为递归函数,它需要引用自身.但是,bar()在一个类中,调用return bar(n-1)不起作用,调用NameError: global name 'bar' is not defined.我该如何处理这种情况?我应该将bar()更改为类或实例方法,允许访问selfcls

Mar*_*ers 31

您可以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)
Run Code Online (Sandbox Code Playgroud)

静态方法毕竟只是包含在类的命名空间中的常规函数​​.

或者,将其定义bar为常规函数:

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

class Foo(object):
    def __init__(self):
        baz=bar(10)
Run Code Online (Sandbox Code Playgroud)

这完全避免了整个问题.

  • @senderle它适用于Python 3,因为没有更多的"未绑定方法"包装器,它们在调用方法时需要`isinstance(self,DefiningClass)`.只适用于`@ staticmethod`的一件事是在一个实例上调用该方法(`Foo().bar(1)`). (3认同)
  • @senderle:方法的第一个参数只是按惯例调用`self`.由于`bar`接受名为`n`的参数,因此它将被用作实例绑定参数.并且Python 3不再强制执行第一个参数的类函数必须是实例检查,调用`class.method(integer)`工作没有错误. (2认同)

lol*_*pop 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)
Run Code Online (Sandbox Code Playgroud)


kin*_*all 6

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

class Foo(object):
    def bar():
        def bar(n):
            if n == 0:
               return "bar"
            return bar(n-1)
        return bar
    bar = staticmethod(bar())
Run Code Online (Sandbox Code Playgroud)

(次要)优点是,当名称改变时,这种情况不太容易破坏.例如,如果你有一个对Foo.bar inside 的引用bar,那么它依赖于Foo继续作为bar定义的类的全局名称.通常是这种情况,但如果不是,那么递归调用会中断.

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


Alp*_*a14 6

您可以在 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)
Run Code Online (Sandbox Code Playgroud)