20

我有以下代码:

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() 更改为类或实例方法,允许访问selforcls吗?

4

5 回答 5

48

您可以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)

这完全避免了整个问题。

于 2012-11-01T18:44:22.833 回答
12

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

class Foo(object):
    def bar():
        def bar(n):
            if n == 0:
               return "bar"
            return bar(n-1)
        return bar
    bar = staticmethod(bar())

The (minor) advantage is that this is somewhat less susceptible to breaking when names change. For example, if you have a reference to Foo.bar inside bar, this relies on Foo continuing to be a global name for the class that bar is defined in. Usually this is the case but if it isn't, then the recursive call breaks.

The classmethod approach will provide the method with a reference to the class, but the class isn't otherwise needed in the method, which seems inelegant. Using the closure will also be marginally faster because it isn't doing an attribute lookup on each call.

于 2012-11-01T20:02:27.000 回答
9

那个怎么样?

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)
于 2012-11-01T18:47:07.833 回答
5

You can define bar() outside of Foo and then bring it in as a staticmethod so that you get all of the benefits of it being a method of the class while not having to close it or reference the class itself. I have needed something like this for class inheritance reasons.

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)
于 2014-02-21T08:13:43.090 回答
0

If the main goal is to run a recursive method, you can use plain methods for this.

I actually never saw the use for this until now. lets say you have integer thresholds you need to test, this pattern can be quite nice and easy: ( even though it can create a bit overheat, so be cautious)

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)
于 2021-06-18T10:03:13.503 回答