2016-10-25 5 views
0

Я определил функцию внутри функции в программе (Python):Определения функции внутри других функций

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

x = 4 
print func2(5) 

Как сфера для й здесь работать, с и без линии, которая переопределяет й = 4 ? Является ли это специфическим для языка поведение?

+1

'def func1:' похоже, не правильный Python. Кроме того, вопросы программирования идут на Stackoverflow. Этот сайт здесь для компьютера * science *. – adrianN

+0

Прежде чем отправлять код, по крайней мере, проведите его через компилятор/интерпретатор, чтобы устранить все очевидные ошибки. Вы заметите, что вызов 'func2' не подходит для определения соответствия. – reinierpost

+0

@adrianN Извините, если цель моего вопроса не ясна. Я был менее обеспокоен тем, что моя программа работала, а не об общей концепции компьютерной науки, поэтому я написал ее в псевдо-псевдокоде и не публиковал ее в StackOverflow. – Jess

ответ

0

Прежде всего: вы слишком ленивы. Прежде чем писать код здесь, по крайней мере, подавайте его интерпретатору или компилятору для рассматриваемого языка, чтобы отсеять очевидные проблемы. В этом случае существует два:

  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, как переменных, так и функций, являются 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 статически охвачены.

+0

Благодарим вас за введение общей концепции в дополнение к исправлению. Это было то, что мне было изначально любопытно при публикации этого вопроса. – Jess

+0

Имейте в виду, что особенности варьируются от языка к языку, что-то еще вам было интересно. – reinierpost