Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conflicting variable and function names in python

Tags:

python

Let's say I've got the following functions:

def xplusy(x, y):
    return x+y

def xplus1(x):
    xplusy = xplusy(x, 1)
    return xplusy

Now if I call a = xplus1(4) it throws the following error:

UnboundLocalError: local variable 'xplusy' referenced before assignment

The error is because of the naming conflict, if I redefine xplus1 as follows:

def xplus1(x):
    s = xplusy(x, 1)
    return s

it works fine.

Why is it so: can't compiler properly distinguish between a variable and a function call?

Any ways around it?

like image 673
sashkello Avatar asked Nov 28 '22 16:11

sashkello


2 Answers

In Python, functions are data, and typing is dynamic. This means that the following lines are valid Python:

def func(x):
    return x + 3

func = 3

func is now an int. The original function func is no longer referenced. The fact that func was originally a function doesn't have any bearing on what types of data can be assigned to it in the future. (This is what "dynamic typing" means.)

Therefore, since there's no static typing, and "function" is a valid data type, it wouldn't make sense for the Python interpreter to distinguish between a function and a piece of data referenced by the same name. Therefore, within a given scope, there's no way to use the same unqualified variable name to mean two different things.

In your particular case, if the code in your xplus1 function meant anything, it would mean "compute the value of xplusy(x,1) and assign that value to the variable xplusy -- thereby losing the reference to the function xplusy." However, within the scope of a function, the interpreter won't let you make an assignment to a variable outside of that scope, so it assumes that by writing an assignment statement, you're introducing a new local variable xplusy. The local variable, however, hasn't been defined yet, so your attempt to call it, xplusy(x,1), fails. The globally defined function is not called as a fall-back because, again, you can't have two unqualified names be identical and point to different data in the same scope.


Another example demonstrating the "no duplication of variable names within one scope" rule (which I actually only just discovered while playing around with the prompt in my attempt to construct this answer):

>>> def f1():
...     a = xplusy(3,4)
...     xplusy = 5
...     print xplusy
...
>>> f1()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f1
UnboundLocalError: local variable 'xplusy' referenced before assignment
>>> def f1():
...     a = xplusy(3,4)
...     print a
...
>>> f1()
7

This demonstrates that it really is the scope, not the statement that requires unique names.


EDIT: This is a really cool post that explains this and other scoping-related behavior: http://me.veekun.com/blog/2011/04/24/gotcha-python-scoping-closures/

like image 53
Kyle Strand Avatar answered Dec 05 '22 14:12

Kyle Strand


In python function is first class object which mean it is as any other object.

More information about What are “first class” objects?

like image 30
emcpow2 Avatar answered Dec 05 '22 15:12

emcpow2