I made a quick script below to test some behaviors after encountering a problem on a larger self learning initiative. I am using python 2.7.x.
#!/usr/bin/python
def test(arg1):
y = arg1 * arg1
print 'Inside the function', y
return y
y = int(raw_input('Enter: '))
test(y)
print 'Outside the function', y
Enter: 6
Inside the function 36
Outside the function 6
However, when the code is as below:
#!/usr/bin/python
def test(arg1):
y = arg1 * arg1
print 'Inside the function', y
return y
y = test(6)
print 'Outside the function', y
Inside the function 36
Outside the function 36
Why does the first code snippet provide 36, 6 and not 36, 36 as in the second case? What suggestions can you make for the function to return the altered value (in this case 36) so that value can be passed into another function.
For context, what I am aiming to do is have the user input a value, send that value to a function. I want that function to perform some logic upon that input, for example test to make sure it meets a certain condition: uses characters [a-zA-z -], then return that value, so that it can be passed to another function. However, I am not asking for support in this
Many thanks for your time, any help is greatly appreciated.
case #1 explained
#!/usr/bin/python
def test(arg1):
y = arg1 * arg1
print 'Inside the function', y
return y; # returning 36
y=int(raw_input('Enter: ')) # here y is 6 as you read from user
test(y) # you are passing 6 and which computes y to be 36, though test is returning 36, but it is not stored in any variable (including y). (not re-assigned, so outside the definition/fucntion, y is still 6)
print 'Outside the function', y # so it is still 6
Case #2 explained
#!/usr/bin/python
def test(arg1):
y = arg1 * arg1
print 'Inside the function', y
return y; # returning 36
y=test(6) # here you received and stored it in y
print 'Outside the function', y # now y is 36
Because you changed the value of y on the second example by setting y = test(6). Set y = test(y) on the first and you will get the same result.
The only difference between the two snippets is that in the second one you reassign y to to the result of calling the function. That is all you need to do.
In the first code, you have a global variable named y, which you assign the value 6 to. When going into the function, you create a local variable, also called y, which you assign the value 6*6=36 to. When you leave the function, you return this value, but do not use it. Then, you print the global y.
In the second code, you assign the returned value (local y = 36) to your global value y, thus making the two printed values to be the same.
Why does the first code snippet provide 36, 6 and not 36, 36 as in the second case?
Because you defined an entirely new y variable whose value is 36, meanwhile the value outside the function is 6.
In the second case, you still have two y variables, but the one towards the bottom (almost said first one, because it technically is executed first) is the return value of the method
You don't assign the result of test(y) the variable y in your code
y=int(raw_input('Enter: '))
# y= 6
# here you need to assign y= test(y)
test(y)
# test result is 36, but not saved to y
print 'Outside the function', y
# print 6
There are two reasons the output is not the same:
- the scopes are different, in your first example, the y you assign in the function is not the same the y outside of it, even if they have the same name. To (over)simplify, you can think that, when you start a new function, there is a brand new memory space created and, inside of it, there is nothing already present (except the modules names imported, the argument to the function, ...), so, even if you do an assignation to y inside the function, it is a brand new y, and, its life stops when the function is over.
- in the second example, you take to output of your function and put it in y, in the first example, the output is lost since not used.
To illustrate my first point:
#!/usr/bin/python
def test(arg1):
y = arg1 * arg1
print 'Inside the function', y
return y;
test(3)
print y
This will raise NameError, because, outside the function, y does not exists.
I invite you to read and understand this very simple explanation Getting Started with Python - Variable scope
Related
Python
Can anyone help me to understand this code, I am new to Python, how does this function work?
def makeInc(x):
def inc(y):
return y + x
return inc
incOne = makeInc(1)
incFive = makeInc(5)
print(incOne(5)) # returns 6
print(incFive(5)) # returns 10
Higher-order functions
Functions like makeInc that in turn, return another function are called higher order functions. Usually, functions are known to accept data as input and return data as output. With higher order functions, functions instead of data, either return code as output or accept code as input. This code is wrapped into a function. In Python, functions are first class citizens which means functions, just like data, can be passed around. For instance:
myvariable = print
Notice, how I have assigned print to myvariable and how I have dropped the parentheses after print Functions without parentheses are called function objects. This means myvariable now is just another name for print:
print("Hello World!")
myvariable("Hello World!")
Both of the above statements do the exact same thing. What can be assigned to variables can also be returned from functions:
def myfunction():
return print
myfunction()("Hello World!");
Now let's look at your example:
def makeInc(x):
def inc(y):
return y + x
return inc
makeInc is a function that accepts a parameter called x. It then defines another nested inner function called inc which takes in a parameter called y. The thing about nested functions is that they have access to the variables of the enclosing function as well. Here, inc is the inner function but it has access to x which is a variable of the enclosing outer scope.
The last statement return inc returns the inner function to the caller of makeInc. What makeInc essentially is doing, is creating a custom function based on the parameter it receives.
For instance:
x = makeInc(10)
makeInc will first accept 10 and then return a function that takes in an argument y and it increments y by 10.
Here, x is a function that takes in any argument y and then increments it by 10:
x(42) # Returns 52
nonlocal
However, there is a caveat when using nested functions:
def outer():
x = 10
def inner():
x = 20
inner()
print(x) # prints 10
Here, you would assume that the last print statement will print 20. But no! When you assign x = 20 in the inner function, it creates a new local variable called x which is initialized to 20. The outer x remains untouched. To modify the outer x, use the nonlocal keyword:
def outer():
x = 10
def inner():
nonlocal x = 20
inner()
print(x) # prints 20
If you are directly reading x inside inner() instead of assigning to it, you do not need nonlocal.
What is happening here is that makeInc() returns a function handle pointing to specific implementation of inc(). So, calling makeInc(5) "replaces" the x in inc(y) to 5 and returns the callable handle of that function. This handle is saved in incFive. You can now call the function as defined (inc(y)). Since you set x=5 before, the result will be y+5.
Here is a very simplified example of what I am trying to do:
x = 3
def f():
print(x)
x = 5
f() #f prints 5 but I want it to print 3.
Is there a way, when declaring the function, to turn x into a constant that points somewhere other than the global variable x? I can't provide arguments to the function.
This is a pretty common trick (you usually see it in lambda expressions that want to bind a particular value within a loop):
x = 3
def f(x=x):
print(x)
x = 5
f() # prints 3
The trick is that default parameter values are evaluated at the time of function definition, so in the expression x=x, the x on the right hand side is evaluated (producing the value 3) and then stored as the default value of the x parameter in the function (which shadows the x in the outer scope).
You could equivalently write:
x = 3
def f(n=x):
print(n)
x = 5
f() # prints 3
which has the same result, but doesn't shadow the x variable.
From what I understand, you seem to want x to hold two values simultaneously - which is what complex data structures are for. A list would work fine, or a dict:
>>> x = [3]
>>> def f():
... print(x[0]) # always refers to first element. Functionally constant.
...
>>> x.append(5)
>>> f()
3
>>>
However, it sounds like you really have an XY problem, where you're asking about your solution instead of your actual problem. Go back to your code and check if this seems to be the case. If so, we might be able to point you towards a better way of solving your real issue.
I am new in stackflow. I will so thankful if someone can help me.
I have to resolve this:
Define a nested function called nested_sum, where in the first part of the function you accept an argument called x, and in the second part (the function inside) you take another argument called y. In the function inside you have to calculate the sum of x and y.
To test your function create a variable called res_1 where you pass the x argument to nested_sum, and then create a variable called res_2 where you pass the y argument of the res_1 variable to get the final solution.
Have x equal 2 for res_1 and y equal 10 for res_2.
After looking on the internet I found a similar code, but I don't really understand how it works!
def nested_sum(x):
def in_sum(y):
return x+y
return in_sum
res_1 = nested_sum(2)
res_2 = res_1(10)
Thank you
First of all you need to realise res_1 is simply the in_sum() function.
Therefore as per your code:
nested_sum(2) puts x = 2 and then returns the in_sum() function.
res_2 = res_1(10) = in_sum(10)
Therefore x = 2 and y = 10, so thus
x + y = 2 + 10 = 12
You can write the code (easier to understand) as follows:
def nested_sum(x):
def in_sum(y):
return x+y
return in_sum
res_1 = nested_sum(2) #nested_sum return in_sum(y) location with x=2 so --> res_1= in_sum (2+y)
res_2 = res_1(10) #Cause res_1 points in_sum(2+y) res2=in_sum(2+10)=12
First of all, function in Python is an object. Think of it as a piece of paper where it is written what arguments it needs an what to do with them.
nested_sum(2) creates a new piece of paper where it is writen: «take the 𝑦 argument, add 2 to and return it.»
nested_sum(𝑥) creates a new piece of paper where it is writen: «take the 𝑦 argument, add 𝑥 and return it.»
Let me rename variables in your code:
def increaser_function_maker(x):
def the_new_function(y):
return x + y
return the_new_function
function_that_takes_number_and_adds_two_to_it = increaser_function_maker(2)
result = function_that_takes_number_and_adds_two_to_it(10)
There is another way to make this function. Maybe it will be easier to understand:
def increaser_function_maker(value_to_add):
return lambda i: i + value_to_add
def func(x):
print "inside function" ,id(x)
x = 2
x = 50
print "outside function" ,id(x)
print 'Value of x before function call is', x
func(x)
print 'Value of x after function call is', x
output:
outside function 6486996
Value of x before function call is 50
inside function 6486996
Value of x after function call is 50
Assuming that id() gives memory location of object. Even though both are saving at the same location, if x value is changed in func(), it is not effected outside.
Ah, but the id(x) call in the function references the global x that was passed to the function, but the x = 2 creates a new local x. Try this:
def func(x):
print "inside function", id(x)
x = 2
print "still inside function", id(x)
x = 50
print "outside function" , id(x)
print 'Value of x before function call is', x
func(x)
print 'Value of x after function call is', x
typical output
outside function 168950596
Value of x before function call is 50
inside function 168950596
still inside function 168951172
Value of x after function call is 50
An assignment usually changes the binding between name and object (if you don't do sth like x = x, of course). It doesn't do any alterations on the object (which wouldn't work on ints anyway as they are immutable, but just as a side note)
So in this case your x inside the function points to the 50 object until you change it. Then it points to a different object. The object itself is not affected.
To point out what happens step by step:
outside x points to int object with value 50
function call: inside x points to same object
inside x is changed to point to different object, having value 2
return: outside x still points to 50.
if u want know more about it, i think u need understand basic python fully.
point about your question:
mutable object as parameter
The function gets a reference to that object and could mutate it, but if you re-bind the reference in the method, outer scope know nothing,after done, the outer reference would still point the original object.
immutable object as parameter
Still can't re-bind the outer reference, and can't even mutate this object.
update for comments: so u pass x(Integer immutable) to function call, you can't mutate this object. and u you re-bind the x refer in the function, outer scope know nothing,after done, the outer reference would still point the original integer 50 object.
I have a small piece of code to understand how to return values that can be used in other sections of the code. In the following i only want to return the variable z, or the value snooze. But it does not work. Please can someone help me to understand why this will not work?
import time
def sleepy(reps, snooze):
t = []
for x in range(reps):
x = time.time()
time.sleep(snooze)
y = time.time()
z = y - x
t.append(z)
print 'difference = ', z*1000
print 'total:', (sum(t)/reps) * 1000
return z
sleepy(10, 0.001)
print z # does not like this.
If I print snooze it also grumbles. Why is that?
z is a local variable in your sleepy() function; it is not visible outside of that function.
Your function does return the value of z; assign it:
slept = sleepy(10, 0.001)
print slept
I used a different name here to illustrate that slept is a different variable.
You should not try to print z or snooze because they have a scope that is limited to the definition of the function. When you do: sleepy(10,0.001) then the value 10 is assigned to reps and the value 0.001 is assigned to snooze.
And then the things that you want are done with these variables. In the meantime a new variable called z is created with the scope inside the definition of the function. And then this value is returned. And as soon as the last statement has been executed then all the variables that are created inside the definition are deleted.
So you must do:
a = sleepy(10,0.001)
print a
This will print the value of a which is the value that you returned from inside the function.
Also you can print z if you declare it as global, that is:
import time
def sleepy(reps, snooze):
t = []
for x in range(reps):
x = time.time()
time.sleep(snooze)
y = time.time()
global z ##notice this line has been changed.
z = y - x
t.append(z)
print 'difference = ', z*1000
print 'total:', (sum(t)/reps) * 1000
Now the value to be returned is in z and you can print it as so:
sleepy(10,0.001)
print z
When you return something from a function you are calling, the syntax is as follows:
p = sleepy(10,0.001)
print p
z and snooze are local variables to the function.
You need to assign the result of the function to a variable to have it available after the function call.
z is a local variable.when you return z it not actually returns variable z instead its
returns the value which is present in z so u need to store it in another variable and print that variable
or you can just use
print sleepy(10, 0.001)