0

I defined a function inside of a function in a program (Python):

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

x = 4
print func2(5)

How does the scope for x here work, with AND without the line that redefines x=4? Is this language-specific behavior?

Raphael
  • 9,779
  • 5
  • 63
  • 94
Jess
  • 1,515
  • 3
  • 23
  • 32
  • 1
    `def func1:` doesn't seem to be correct Python. Also, programming questions go on Stackoverflow. This site here is for computer *science*. – adrianN Oct 25 '16 at 07:34
  • Before you post code, at the least feed it through the compiler/interpreter to eliminate all obvious errors. You'll notice that the call to `func2` doesn't fine a matching definition. – reinierpost Oct 25 '16 at 09:53
  • @adrianN Apologies if the intent of my question wasn't clear. I was less concerned about getting my program to work than learning about the general computer science concept, which was why I wrote it in pseudo-pseudocode and did not originally post it in StackOverflow. – Jess Oct 25 '16 at 14:37

1 Answers1

0

First of all: you're being too lazy. Before you write code here, at least feed it to an interpreter or compiler for the language in question to weed out the obvious problems. In this case, there are two:

  1. Your example code won't compile due to a syntax error. Fixing it by adding () on the definition of func1.
  2. Your example code won't run due to func2 being undefined where it is called.

So let's try

#!/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

Three lines are commented; they produce errors when uncommented.

As you can see, Python definitions, of both variables and functions, are local by default: when defined within a function, they only apply within that function, and cannot be used elsewhere.

Variables defined outside a function can be used inside the function. However, they can only be read, not written. This explains why we can use x inside func2 but cannot assign to it; when x = x + 1 is uncommented, it is interpreted as applying to a different x variable inside func2, which is why we'll get an error complaining that it is used uninitialized.

In addition, Python has global variables, which can be used anywhere in the program; such variables must be marked global explicitly.

This is very similar to PHP (in which variables can also be marked as global) and fairly similar to many other languages, such as C (which has no global, but the similar extern).

You're trying to have a function (func2) use a variable (x) defined in the context of its definition, then call the function outside the context where x is defined and still have it work. Functions that can do this are known as closures.

We've just seen that Python only has partial support for closures: the function can read such variables, but cannot modify them. This is already better than many other languages. However, a full closure can also modify such variables.

For instance, the following is valid Perl code:

#!/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

Full closure support is traditionally associated with dynamic scoping (i.e. making definitions executable statements, evaluated at run time). This is because it was introduced by Lisp, which was dynamically scoped, and support for it is rare in languages that use static (lexical) scoping (in which the scope of definitions is determined at compile time, not at run time). But all of the variables and function definitions in this Perl code are statically scoped.

Community
  • 1
  • 1
reinierpost
  • 8,425
  • 1
  • 38
  • 70
  • Thank you for introducing the general concept in addition to the fix. This was what I was originally curious about when posting this question. – Jess Oct 25 '16 at 14:38
  • Be aware that the specifics vary from language to language, something else you were curious about. – reinierpost Oct 25 '16 at 22:38