I would like to ask the difference between return and print.
def x(n):
a=1
print a,n,
return a
print x(2)
If I type x(2) it will output on the console: 1 2 right?
Is the variable a printed a second time only when I type print x(2)?
When you write
print X(2)
then the function X gets called with 2 as a parameter, let's go inside it:
a=1
print a,2,
return a
it'll print 1 and 2, then it returns a which has the value 1.
The returned value (1) gets printed since you wrote print X(2).
If you have wrote X(2) (without print), you would get 1 and 2 printed, and the returned value will be unused.
def x(n):
print n+1
Now, when x(5) is called, it will print 6 to the console. However, if you did y=x(5), the value of y would be None.
Now:
def x(n):
return x+1
If you called x(5), it would still print 6 to the console. But, if you did y=x(5), the value of y would be 6, not None
The two appear to do similar things, but are quite different.
Most of the time, you'll be using return as an output for a function. Using print implies just that: printing something as a string (perhaps to a file or interpretor, etc).
Also, you can't do anything with a value printed by a function. Returning a value provides you more in this regard since it isn't "garbage collected" like a printed value.
Return also allows you to break out of a function.
>>> def x(y):
... squared = y ** 2
... return squared
...
>>> x(2)
4
>>> z = x(2)
>>> z
4
>>> def a(b):
... squared = b ** 2
... print(squared)
...
>>> a(2)
4
>>> c = a(2)
4
>>> c
>>>
In this example, I have two functions: x and a. Both take one positional argument and either return or print that valued squared.
Notice that if I assign the function with an argument to a variable, I can return that value by calling the variable with the function returning a value but not with a function printing the value.
Related
In Python, does a function just execute it’s code block & not store it unless we use a return statement?
When we print variables & expressions I understand we are printing values.
So I am thinking that a function performs it’s code block & then does not save that result unless we return it? Is this what’s happening in the computer?
Example 1
def add(a,b):
nums = a + b
print(add(2,4)+2)
Error
But when we use the return value statement it works
Example 2
def add(a,b):
nums = a + b
return nums
print(add(2,4) + 2)
Output: 8
The error was caused in the first example because the function just executed it’s code block & did not save the result therefore resulting in an error due to not being able to add None to an integer(2)?
&
It worked in example 2 because we saved the functions result with the return statement giving us an integer; Therefore allowing the print statement to print the result of the functions integer + the integer we added it to in the expression?
In python, functions are blocks of code that execute some logic of some sort (sometimes based on arguments passed into them and sometimes not). They are very broad and can do many different kinds of things depending on how they are constructed. I'm not exactly sure what you mean by "store the results" but hopefully some of the following explanation will help.
All variables created in a function are stored with the "local" scope, meaning that they are only existent when the function is running and are deleted the moment the function terminates. For example, in the following code, you cannot access the variable x after the function terminates:
def example():
x = 'Hello World'
print(x) #This prints: Hello World
example()
print(x) #This will give you a Reference error
If that is what you mean by "stores the results" then you are right: those results will not be stored. You can, however, declare a variable inside of a function to be a global variable, meaning that it can be accessed outside of the function too:
def example():
global x = 'Hello World'
print(x) #This prints: Hello World
example()
print(x) #This prints: Hello World
When you use the return statement in a function you are just telling the compiler that if a variable is set equal to a function call of said function, whatever follows the return statement is what that variable should be set equal to. However, simply returning a value does not "store" it. See the following code:
def example():
x = 'Hello World'
return x
example()
print(x) #This will still cause a reference error
x = example()
print(x) #This prints: Hello World
One final thing to note about the code above: as long as two variables are in different scopes, they can have the same name and not cause an error. The x inside the function is in a local scope and the x outside of the function is in the global scope which is why that does not cause an error.
Welcome to Stack Overflow. When I was learning programming, it helped me to think of calls to functions using an analogy to variables in math. In most languages, you can think of "substituting" the return value in for the function call, the same way you can substitute a literal number into a variable.
In math, you can do this:
m = 4
b = 2
y = m * x + b # Plug 4 and 2 in for "m" and "b"
y = 4 * x + 2
It's the same with value-returning functions:
def foo():
return 'bar'
>>> x = foo() # Plug the return value 'bar' in for "foo()"
>>> x
'bar'
In Python, when a function has no explicit return, the default return value is None. So:
def foo():
print('bar')
# No return, so Python implicitly returns None
>>> x = foo() # Plug the return value None in for "foo()"
'bar'
>>> x
None
the function define local variable even same name as global variable so when it executed if you don't return something or store the result in global variable the result not appears outside function
example
x = 10
def test():
x= 15
test()
print(x) # result 10
but if use global keyword you can access to global variable like this
x = 10
def test():
global x
x= 15
test()
print(x) #result 15
or if you return the value
x = 10
def test():
x= 15
return x
x = test()
print(x) #result 15
I use 2 codes. I want program 1 to recieve the value from program 2.
file 1:
from OpenUSB import transmitter
def valuepullup():
newval = transmitter()
print(newval)
valuepullup()
file 2:
def transmitter():
print (2)
result I get is:
2
None
I would love use the value which just got send over. As the current situation the None spoils it.
Is there a way to stop the none from coming with the 2.
Thanks in advance
You have two options here, either simply use a return instead of a print in your transmitter function, or just call your transmitter without calling print. What is happening here is that you are both printing the return of the function, which is None (because not specifying a return, will return None by default), and the print inside the function.
Observe:
>>> def transmitter():
... print (2)
...
>>>
>>>
>>> transmitter()
2
>>> print(transmitter())
2
None
>>>
More closely to your example, look what happens when you assign transmitter to a value:
>>> newval = transmitter()
2
>>> print(newval)
None
>>>
So, with respect to your code, you should do
def transmitter():
return 2
Which actually makes the code inside your valuepullup make much more sense. You are looking to actually store the 2 in newval. So, you should be returning the 2 from your transmitter function instead so that newval actually holds 2 now. As it stands in your code, it holds None, because it will hold the return of transmitter. Which, as explained, is None. So, your code would now be:
from OpenUSB import transmitter
def valuepullup():
newval = transmitter()
print(newval)
def transmitter():
return 2
valuepullup()
Now, when you print newval it will in fact be 2.
You did not return anything from def transmitter():. instead of printing 2, return 2.
I just realized that the pythonic swap doesn't always work.
def swap(x,y):
x,y = y,x
a = 1
b = 2
swap(a,b)
print b
result: 2
Why does the pythonic way to swap variables not work in this case? Do I need temporary a variable?
In the first line of the function definition
def swap(x,y):
x and y are so called formal parameters.
When you call
swap(a, b)
you are passing in a and b as actual arguments.
What happens now is that Python creates new names for the actual arguments you have passed in.
Inside the function body x is now a new name for the integer object in memory which also has the name a. y is now a new name for the integer object in memory which also goes by the name b. This is why Python is neither call-by-value nor call-by-reference, but best described as call-by-assignment.
Contrary to popular belief, calling functions and assignment works exactly the same way for mutable and immutable parameters. You will see the same behavior you are observing for mutable values:
>>> def swap(x,y):
... x,y = y,x
...
>>> a = [1]
>>> b = [2]
>>> swap(a,b)
>>> a
[1]
>>> b
[2]
So once you understand how assignments work in Python, you will also have understood how function calls work.
To make an example: If you did not write a function, your code would have been equivalent to:
a = 1
b = 2
x = a
y = b
x,y = y,x
del x
del y
In line 3, you are creating a new name x for the integer object which also goes by the name a. Line 4 follows the same logic.
In line 5, you are creating the tuple (y, x) with the value (2, 1) on the right hand side, which is then unpacked, i.e. the name x is reassigned to the value 2 and the name y is reassigned to the value 1:
>>> a = 1
>>> b = 2
>>> x = a
>>> y = b
>>> x,y = y,x
>>> x
2
>>> y
1
The important thing to note here is that a and b never stopped to be names for the value 1 and 2 respectively:
>>> a
1
>>> b
2
The last two lines just unbind the names x and y which is roughly equivalent to what happens in your function once you exit its scope. Note that the names a and b are still bound after unbinding x and y.
>>> a
1
>>> b
2
You never returned and assigned the results. Otherwise, as Joran said, you are only creating local variables in the function. For example:
def swap(a, b):
print "swap called"
return (b,a)
a = 1
b = 2
print a,b
a,b = swap(a,b)
print a,b
Results in the following being displayed:
1 2
swap called
2 1
You need to return something; the swapped vars
I'm a beginner trying to write a text based game, something like Monopoly. Since I learned about functions I thought the best way would be to define a function for each square. Then, I would put the functions in a list and randomly call them. The problem is the functions might require different number of arguments or no argument.
from random import randrange
def foo1(param_of_foo1):
x = param_of_foo1 + 1
print "x is:", x
def foo2(param_of_foo2):
y = param_of_foo2 + 2
print "y is:", y
def foo3(useless_param):
print "I have a parameter but I don't really need it..."
list_of_foo = [foo1, foo2, foo3]
arg = 0
function_index = randrange(0,3)
print "Function index is:", function_index
if function_index == 0:
arg = 4
elif function_index == 1:
arg = 10
list_of_foo [function_index](arg)
As you can see this seems to work but it is not an elegant solution. I don't like that I had to define the third function with a parameter even if it doesn't need it, of course. And I also don't like that I have to specify a condition for some functions to let them know what they should use as arguments.
Surely there must be a better way to do this. There always is. Thank you and sorry if this is stupid or it has already been asked. I couldn't find an answer.
Updated code:
from random import randrange
from functools import partial
def foo1(arg_of_foo1):
x = arg_of_foo1 + 1
print "x is:", x
def foo2(arg1_of_foo2,arg2_of_foo2):
y = arg1_of_foo2 + arg2_of_foo2
print "y is:", y
def foo3():
print "I don't need a parameter so I don't have one."
a = 0
b = 0
while b <= 100:
print'='*20
random_number = randrange(0,3)
a += 1
b += 10
print "a is:", a
print "b is:", b
print "r_n is:", random_number
print '-'*10
raw_input("[Enter] to execute random function")
list_of_foo = [partial(foo1,a), partial(foo2,a,b), partial(foo3)]
list_of_foo[random_number]()
This code gets rid of the conditional statements and of the unnecessary parameters.
Thank you, inspector!
There are three things that you can do:
Use *args in the function definition
Rewrite your functions to take a list (or tuple, or dict) as the only parameter, and read the actual parameters out of it
Use ast to read the function signature, and give it the correct number of parameters (left out for now)
Using *args
In python, you can define *args to be the list of arguments your function gets, which will assign the sequence of arguments to a list called args:
In [113]: def func(*args):
.....: print "the arguments are:", ' '.join(args)
.....:
In [114]: func()
the arguments are:
In [115]: func('a')
the arguments are: a
In [116]: func('a', 'b')
the arguments are: a b
So, with that in mind, you can do:
def foo1(*args):
param_of_foo1 = args[0] # any other arguments will be discraded
x = param_of_foo1 + 1
print "x is:", x
def foo3(*uselessArgs):
print "I have a parameter but I don't really need it..."
You can still call foo3() and foo3(1,2,3)
Using lists
This is the same idea as before, but you call with a list of arguments:
def foo1(L):
param_of_foo1 = L[0] # other entries will be ignored
This will need to be called with a list of params: foo1([1]) or foo1([1,2,3])
def foo1(arg):
print "I got this as my argument:", arg
Now, foo1([1,2,3]) will give:
I got this as my argument: [1,2,3]
Since arg behaves like any other list (just like in the *args case), you shoul dbe able to pull out any number of arguments (as long as they are supplied). So since the maximum number of arguments your functions require is 1, always supply a list of at least one argument, and any extras will be ignored (especially by foo3)
There is another way, using ast, but I don't think that's what you're after, so I'll leave it out for now (comment, and I'll add it in)
If, on the other hand, you are only ever going to call foo1 with 4 and foo2 with 10, then this should work for you:
>>> import functools
>>> import random
>>> def foo1(param_of_foo1):
... x = param_of_foo1 + 1
... print "x is:", x
...
>>> def foo2(param_of_foo2):
... y = param_of_foo2 + 2
... print "y is:", y
...
>>> def foo3(useless_param):
... print "I have a parameter but I don't really need it..."
...
>>> f = functools.partial(foo1, 4)
>>> f()
x is: 5
>>> list_of_foo = [functools.partial(foo1, 4), functools.partial(foo2, 10), functools.partial(foo3, 'discarded argument')]
>>> random.choice(list_of_foo)()
y is: 12
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
y is: 12
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
y is: 12
>>> random.choice(list_of_foo)()
I have a parameter but I don't really need it...
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
x is: 5
>>> random.choice(list_of_foo)()
x is: 5
>>>
Just do fn(*args) for unknown number of parameters, or unknown types of parameters.
For example:
def func(a):
# how to get the name "x"
x = 1
func(x)
If I use inspect module I can get the stack frame object:
import inspect
def func(a):
print inspect.stack()
out:
[
(<frame object at 0x7fb973c7a988>, 'ts.py', 9, 'func', [' stack = inspect.stack()\n'], 0)
(<frame object at 0x7fb973d74c20>, 'ts.py', 18, '<module>', ['func(x)\n'], 0)
]
or use inspect.currentframe() I can get the current frame.
But I can only get the name "a" by inspect the function object.
Use inspect.stack I can get the call stack:"['func(x)\n']",
How can I get the name of actual parameters("x" here) when call the func by parsing the "['func(x)\n']"?
If I call func(x) then I get "x"
if I call func(y) then I get "y"
Edit:
A example:
def func(a):
# Add 1 to acttual parameter
...
x = 1
func(x)
print x # x expected to 2
y = 2
func(y)
print y # y expected to 3
Looking at your comment explanations, the reason you are trying to do this is:
Because I want to impelment Reference Parameters like in C++
You can't do that. In python, everything is passed by value, but that value is a reference to the object you pass. Now, if that object is mutable (like a list), you can modify it, but if it's immutable, a new object is created and set. In your code example, x is an int which is immutable, so if you want to change the value of x it, just return its new value from the function you are invoking:
def func(a):
b = 5 * a
# ... some math
return b
x = 1
x = func(x)
So what if you want to return multiple values? Use a tuple!
def func(a, b):
a, b = 5 * b, 6 * a
# ...
return b, a
a, b = 2, 3
a, b = func(a, b)
That is feasible, up to a point - but nonetheless,useless in any kind of "real code".
You can use it for backyard magic tricks:
Just retrieve the calling stack_frame like you are doing,
then loop linearly through the variables available in the calling frame for
one that references the same object you got as a parameter. The variables are in the
f_locals and f_globals dictionaries which are attributes of the frame object.
Of course, the parameter passed may not be in a variable name to start with:
it might be a constant in the caller, or it might be inside a dict or a list.
Either way, as #Nasser put it in the answer: it is not the way Python works. Objects exist in memory, and variable names, in each scope, just point to those objects. The names themselves are meaningless otherwise.
import inspect
from itertools import chain
def magic(x):
# note that in Python2, 'currentframe' could get a parameter
# to indicate which frame you want on the stack. Not so in Python3
fr = inspect.currentframe().f_back
for var_name, value in chain(fr.f_locals.items(), fr.f_globals.items()):
if value is x:
print ("The variable name in the caller context is {}".format(var_name))
def caler():
y = "My constant"
magic(y)
use lists as references
def func(a):
a[0] = a[0] + 1
x = [1]
func(x)
print x[0] # x expected to 2
y = [2]
func(y)
print y[0] # y expected to 3
This is my final solution. Use ast to parse the function statement and get the args.:
import inspect
import re
import ast
def func(a,b,c):
stack = inspect.stack()
stack_pre = stack[1]
function_call_string = ';'.join( stack_pre[4] ).strip('\n')
ret = re.search(r'(%s[ ]*\(.*\))' % func.func_name, function_call_string)
striped_function_call_string = ret.group()
parser = ast.parse(striped_function_call_string)
frame = inspect.currentframe()
for arg in parser.body[0].value.args:
iter_frame = frame.f_back
while iter_frame:
if arg.id in iter_frame.f_locals:
iter_frame.f_locals[arg.id] += 1
break
iter_frame = iter_frame.f_back
x=1;y=2;z=3;func(x,y,z)
print x,y,z
Out:
2 3 4