我有以下代码:
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()更改为类或实例方法,允许访问self
或cls
吗?
答案 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)