Прежде всего: вы слишком ленивы. Прежде чем писать код здесь, по крайней мере, подавайте его интерпретатору или компилятору для рассматриваемого языка, чтобы отсеять очевидные проблемы. В этом случае существует два:
- Ваш примерный код не будет скомпилирован из-за синтаксической ошибки. Исправление, добавив
()
по определению func1
.
- Ваш пример кода не будет запущен из-за того, что
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, как переменных, так и функций, являются local по умолчанию: при определении внутри функции они применяются только в пределах этой функции и не могут использоваться в других местах.
Внутри функции могут использоваться переменные, определенные вне функции. Однако они могут быть только читать, а не письменный. Это объясняет, почему мы можем использовать x
внутри func2
, но не можем назначать ему; когда x = x + 1
раскоментирован, он интерпретируется как применимый к другой переменной x
внутри func2
, поэтому мы получим ошибку, жалуясь, что она используется неинициализированно.
Кроме того, 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 статически охвачены.
'def func1:' похоже, не правильный Python. Кроме того, вопросы программирования идут на Stackoverflow. Этот сайт здесь для компьютера * science *. – adrianN
Прежде чем отправлять код, по крайней мере, проведите его через компилятор/интерпретатор, чтобы устранить все очевидные ошибки. Вы заметите, что вызов 'func2' не подходит для определения соответствия. – reinierpost
@adrianN Извините, если цель моего вопроса не ясна. Я был менее обеспокоен тем, что моя программа работала, а не об общей концепции компьютерной науки, поэтому я написал ее в псевдо-псевдокоде и не публиковал ее в StackOverflow. – Jess