John Tera
John Tera

Reputation: 31

Passing parameter to inner function

I have a function with inner function. I wonder what is a proper way to pass variables to inner function. From what I can see tables are passed by default, although I am not sure whether this is a undocumented workaround or python design.

def function():
    def inner_function():
        if a[0] > b[0]:
            print("a[0] = {0}, b[0] = {1}".format(a[0], b[0]))
            tmp = c
            c = d
            d = tmp
        
    a = [4, 3]
    b = [2, 1]
    c = 1
    d = 2
    
    inner_function()
    
function()

python test.py output:

$ python test.py a[0] = 4, b[0] = 2 Traceback (most recent call last):

File "test.py", line 16, in

function()

   File "test.py", line 14, in function

inner_function()

   File "test.py", line 5, in inner_function

tmp = c

UnboundLocalError: local variable 'c' referenced before assignment

What is a proper way to pass variables from "function" to "inner_function"? Is there any other way than by parameter? Why there is an error on "c" variable reference and not on "a" table?

Upvotes: 2

Views: 4373

Answers (4)

Lefty G Balogh
Lefty G Balogh

Reputation: 1888

I guess a Pythonic way definitely refers to a duck and a rabbit, possibly even a knight. I'd also second @Metareven on passing them in as arguments as Python has a very succinct way of handling them. This way you do not need to worry about @global variables. And you have a good idea about what goes in and as suggested what comes out.

def function(duck):
    def inner_function(rabbit):
        if rabbit[0][0] > rabbit[1][0]:
            print("a[0] aka the first one behind the rabbit = {0}, \nb[0] aka the second one behind the rabbit = {1}".format(rabbit[0], rabbit[1]))
            tmp = rabbit[2]
            rabbit[2] = rabbit[3]
            rabbit[3] = tmp
    inner_function(duck)

#Let's sort out the arguments
a = [4, 3]
b = [2, 1]
c = 1
d = 2


function([a,b,c,d])

The function call returns the following:

python innner.py
a[0] aka the first one behind the rabbit = [4, 3], 
b[0] aka the second one behind the rabbit = [2, 1]

Has this answered your question?

Upvotes: 0

Eypros
Eypros

Reputation: 5723

Although your question has been answered I am not sure it is clear why your code produce this error.

Anyway to make it clear the line that causes problem is c = d although your interpreter disagrees. Let me explain a bit. You are inside inner_function() and without these lines (c = d and d = tmp) you are referring to variables a, b, c and d assigned outside of inner_function(). So, implicitly you are referring to these variable (a, b, c and d that is) as global.
The moment you assign a value to a variable inside an inner function then the interpreter consider it to be local variable of this function. In this case c is considered local now (since there is an assignment inside inner_function() even after the statement the interpreter complains about tmp = c). So, normally the interpreter complains about a variable it has not been assigned a value but it's being accessed anyway.

So to make it clear, python does not distinguish between type of variable (as for example java does).

What is a proper way to pass variables from "function" to "inner_function"?

Use parameters is the proper way.

Is there any other way than by parameter?

As mentioned by others you can use global variables but it's not recommended as approach.

Why there is an error on "c" variable reference and not on "a" table?

As I mentioned before there is no distinction between different types of variables. What make them different is that you are assigning in variable c a value but just accessing the value of a for example in the other case.

This specific answer (also mentioned by @raul.vila) provides a good explanation.

Finally, since it's not clear what you are trying to achieve here. There is a difference if you are trying to print a global (even implicit) variable in an inner function or you are trying to change the value of a global variable for inside an inner function.

Upvotes: 0

M.H Mighani
M.H Mighani

Reputation: 198

you need to state c and d variables as global (by the way this is not a good idea )

def function():
global c,d
a = [4, 3]
b = [2, 1]
c = 1
d = 2
def inner_function():
    if a[0] > b[0]:
        global c,d
        print("a[0] = {0}, b[0] = {1}".format(a[0], b[0]))
        tmp = c
        c = d
        d = tmp
inner_function()

Upvotes: 0

raul.vila
raul.vila

Reputation: 1984

AFAIK c is throwing an error because is assigned inside inner_function so it is a different variable than the c variable defined in function. Variables a and b work because they are only read at inner_function so they are not being redefined. Renaming c and d to new_c and new_d make it works.

https://pyfiddle.io/fiddle/184e1778-adb7-4759-8951-da699751c31e/

More info about Python nested functions variable scoping

def function():
    def inner_function():
        if a[0] > b[0]:
            print("a[0] = {0}, b[0] = {1}".format(a[0], b[0]))
            tmp = c
            new_c = d
            new_d = tmp

    a = [4, 3]
    b = [2, 1]
    c = 1
    d = 2

    inner_function()

function()

Upvotes: 2

Related Questions