1

python中函数内部的函数本身的范围是什么?我的问题出现了,因为我终于想到冒险进入递归(尽管我没有足够的能力来完全理解它)。我正在使用 Eclipse (PyDev) 并在类内,例如:

每本书中普遍存在的一个简单的阶乘递归示例是:

def factorial(n):
       if (n==0):
           return 1
       else:

           return n*factorial(n-1)

在另一个示例中,在类内部:

class test:

    def factorial(self,n):
       if (n==0):
           return 1
       else:
           return n*factorial(n-1)

我必须使用self.factorial(n-1)吗?(我想,我应该是因为 PyDev 在我不显示时会显示未识别的变量)。为什么在这种情况下需要对对象本身的引用?我是否错过了一些我应该在这里理解的重要事情。

4

4 回答 4

2

factorial在你的第一个例子中是一个全局函数。您递归调用它的事实并没有改变,您仍然首先需要查找函数对象才能调用它。

换句话说,当前被调用的函数没有任何特殊之处。factorial仍然是一个需要取消引用的名称,并且该名称恰好引用了正在执行的函数并不重要。

因此,在您的第二个示例中, wherefactorial是一个方法,没有对该方法的全局引用。相反,您可以通过self引用找到它与类上的任何其他方法一样。

当您定义一个函数时,Python 会在当前范围内以您给它的名称存储对该新函数对象的引用。在全局范围内,这意味着它def foo()成为foo绑定到函数对象的全局名称。您可以通过删除该名称来中断递归:

>>> def foo(): return foo()  # infinite recursion
...
>>> def foo(): return foo()  # infinite recursion
... 
>>> foo
<function foo at 0x108e4b500>
>>> bar = foo
>>> del foo
>>> foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined
>>> bar
<function foo at 0x108e4b500>
>>> bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in foo
NameError: global name 'foo' is not defined

注意NameError这里;我从全局命名空间中删除foo了,但仍然有一个引用bar,我可以调用它。但是函数本身在执行时找不到全局名称foo

否则,Python 函数不会引用它们自己。从函数内部,您不能可靠地检索函数对象本身。您可以做的最好的事情是获取原始函数名称:

>>> def foo():
...     return sys._getframe(0).f_code.co_name
... 
>>> foo()
'foo'
>>> bar = foo
>>> bar()
'foo'

但这并不能保证您仍然可以通过该名称访问该函数对象。

于 2013-10-24T18:01:32.970 回答
1

这与递归无关。如果您定义任何方法,甚至是类中的类,您将需要使用selffor 函数和类名本身用于类中的类。让我演示一下:

class Foo(object):

    def happy(self):
        print "Happy"

    def size(self, var):
        self.happy()  # You need to self to call happy
        if var == 1:
            return 1
        else:
            return 1 + self.size(var - 1)  # You need to refer to self

    class Bar:

        def __init__(self):
            super(Foo.Bar, self).__init__()  # You need to refer to Foo

引用类内部的任何内容都需要使用其命名空间。当您创建一个普通函数时,它会成为文件命名空间的一部分。

于 2013-10-24T18:01:07.383 回答
1

为了补充其他答案,这里有一个快速演示

def f():
   return f  # returning itself, but what does f resolve to?

# this is f
f
=> <function __main__.f>
# it is defined in the global scope
globals()['f']
=> <function __main__.f>
# when accessed from within itself, it is still itself
f()
=> <function __main__.f>
于 2013-10-24T18:03:36.903 回答
0

递归是编程之上的概念,但也用于编程内部。

将其与现实世界联系起来:

递归只是对自身内部的事物本身的引用。例如,您可能听说过的首字母缩写词:

GNU Gnu 不是 Unix

这是一个递归首字母缩略词,因为在首字母缩略词内部,该首字母缩略词被陈述。它可能会引发一场关于鸡还是蛋的有趣的形而上学/哲学辩论,因为没有另一个就不能存在,哪个先出现?

与编程有关

如果我可以打破正式定义,让我们将函数的每个调用称为函数的实例

该函数在代码中定义,然后在其内部调用。

函数的定义不是代码的实例,但是当它被调用时,它就变成了它自己的实例。在实例内部,可以调用其他函数。例如,可以在自身内部Function(A)调用。Function(B)

递归只是 when Function(B) = Function(A),因此Function(A)再次调用它并Function(A)在现有实例中启动 的新实例。因为Function(A)是在代码上面定义的,所以处理器所做的只是再次调用代码。它不依赖于它所在的现有实例。

因此,recursion可以真正适用于任何地方。

谷歌搜索的幽默例子,它总是希望你自动更正递归

这有帮助吗?

快乐编码!

编辑:哦,在函数内部调用的函数的范围只是在调用它的函数内部。Function(A)调用Function(B),这意味着Function(B)的范围在内部Function(A)

于 2013-10-24T18:05:09.107 回答