函数内的函数范围(理解递归)

时间:2013-10-24 17:57:42

标签: python

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 个答案:

答案 0 :(得分:2)

第一个示例中的

factorial是一个全局函数。你以递归方式调用它的事实并没有改变你仍然需要查找函数对象才能调用它。

换句话说,被调用的当前函数绝不是特殊的。 factorial仍然是一个需要被解除引用的名称,并且该名称恰好引用正在执行的函数并不重要。

因此,在您的第二个示例中,factorial是一个方法,没有对该方法的全局引用。相反,您可以通过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函数否则,没有自己的引用。从 inside 函数中,您无法可靠地检索函数对象本身。您可以做的最好的事情是获取原始函数名称:

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

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

答案 1 :(得分:1)

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

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

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

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

答案 3 :(得分:0)

递归是一种高于编程的概念,但也用于编程内部。

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

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

GNU    Gnu不是Unix

这是一个递归的首字母缩略词,因为在首字母缩写词中,首字母缩略词是陈述的。它可以导致关于鸡肉或鸡蛋的有趣的形而上学/哲学辩论,因为没有另一个就不能存在,哪个先存在?

与编程相关

如果我可以打破正式定义,让我们调用函数的每个调用 instance

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

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

递归就在Function(B) = Function(A)时,以便再次调用Function(A)并在现有实例内启动Function(A)的新实例。因为Function(A)定义在代码之上,所以处理器都会再次调用代码。它绝不依赖于它位于中间的现有实例。

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

Humorous example of Google search, where it always wants you to auto-correct to recursion

这有帮助吗?

快乐的编码!

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