【问题标题】:Defining functions inside of other functions在其他函数中定义函数
【发布时间】:2016-10-25 05:34:55
【问题描述】:

我在程序(Python)的函数内部定义了一个函数:

def func1:
   x = 5
   def func2(y):
      return x*y

x = 4
print func2(5)

这里 x 的范围如何工作,如果没有重新定义 x=4 的行,则使用 AND? 这是特定于语言的行为吗?

【问题讨论】:

  • def func1: 似乎不是正确的 Python。此外,编程问题在 Stackoverflow 上进行。此站点适用于计算机科学
  • 在发布代码之前,至少要通过编译器/解释器来消除所有明显的错误。您会注意到对 func2 的调用并不能很好地匹配定义。
  • @adrianN 抱歉,如果我的问题的意图不明确。我不太关心让我的程序运行,而是学习一般的计算机科学概念,这就是为什么我用伪伪代码编写它并且最初没有将它发布在 StackOverflow 中。

标签: python scope


【解决方案1】:

首先:你太懒了。在您在这里编写代码之前,至少将其提供给相关语言的解释器或编译器,以消除明显的问题。在这种情况下,有两个:

  1. 由于语法错误,您的示例代码无法编译。通过在func1 的定义上添加() 来修复它。
  2. 由于func2 在调用位置未定义,您的示例代码将无法运行。

那就试试吧

#!/usr/bin/env python

def func1():
   x = 5 
   def func2(y):
      #x = x + 1  # invalid: "x referenced before assignment"
      return x*y  # not invalid! reference to x is fine
   global func3
   func3 = func2

#print func3(5)  # undefined

func1()

print func3(5)
#print func2(5)  # undefined

三行注释;它们在取消注释时会产生错误。

如您所见,Python 对变量和函数的定义默认是本地:在函数中定义时,它们仅适用于该函数,不能在其他地方使用。 p>

在函数外部定义的变量可以在函数内部使用。 但是,它们只能读取,而不能写入。这解释了为什么我们可以在 func2 中使用 x 但不能分配给它;当 x = x + 1 未注释时,它被解释为应用于 func2 内的不同 x 变量,这就是为什么我们会收到错误消息,抱怨它未初始化。

另外,Python有global变量,可以在程序中任何地方使用;此类变量必须明确标记为global

这与 PHP 非常相似(其中变量也可以标记为global),并且与许多其他语言非常相似,例如 C(没有global,但类似的extern)。

您正在尝试让函数 (func2) 使用在其定义上下文中定义的变量 (x),然后在定义 x 的上下文之外调用该函数并且仍然可以工作.可以做到这一点的函数称为闭包

我们刚刚看到Python only has partial support for closures: 函数可以读取这些变量,但不能修改它们。这已经比许多其他语言更好。但是,完全闭包也可以修改这些变量。

例如,以下是有效的 Perl 代码:

#!/usr/bin/env perl

use strict;
use warnings;

my $func3 = sub { 1 };

my $func1 = sub
{
  my $x = 5;
  my $func2 = sub
  {
    my ($y) = @_;
    ++$x;
    $x*$y
  };
  $func3 = $func2
};

#&$func2(5);  # won't compile: func2 is undefined
print &$func3(5), "\n";  # prints 1
&$func1();
print &$func3(5), "\n";  # prints 30
print &$func3(5), "\n";  # prints 35

传统上,完全闭包支持与 dynamic scoping 相关联(即,使定义成为可执行语句,在运行时评估)。这是因为它是由动态范围的 Lisp 引入的,并且在使用 static (lexical) scoping 的语言中很少支持它(其中定义的范围是在编译时确定的,而不是在运行时确定的)。但是这个 Perl 代码中的所有变量和函数定义都是静态作用域的。

【讨论】:

  • 感谢您介绍除修复之外的一般概念。这是我最初发布此问题时的好奇。
  • 请注意,具体情况因语言而异,这是您好奇的其他事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-30
  • 2020-03-04
  • 2018-06-09
  • 1970-01-01
  • 2012-12-17
相关资源
最近更新 更多