The output of following code is
5
3
I am new to Python, could anybody explain to me why?
import sys
def Main():
str='1+2'
print eval(str)
class A:
def __init__(self):
self.x = 5
a = A()
print a.x
if __name__=="__main__":
Main()
Python code is evaluated from top-down, not from Main().
The interpreter sees the a = A() line first, and prints a.x which is equal to 5, then it checks for the if condition and prints eval(str) which is 3.
Hence the output,
5
3
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
This question already has an answer here:
Override global variable inside function not working with Spyder 4
(1 answer)
Closed 1 year ago.
This is probably something obvious, but I'm confused.
I have a Python script test.py:
def t():
print(a)
a = 1
t()
When I run it, it prints 1, as expected:
runfile('C:/Users/Dave/data/Code/Python/lib/test.py', wdir='C:/Users/Dave/data/Code/Python/lib')
1
But when I then interactively type "a = 999" and run t() again, I expect it to print 999. But it prints 1. Why?
runfile('C:/Users/Dave/data/Code/Python/lib/test.py', wdir='C:/Users/Dave/data/Code/Python/lib')
1
a = 999
t()
1
FWIW, I'm running iPython inside Spyder.
Am I correct to think this is strange and not what I should expect?
Screenshot (added):
They are not the same variables:
def t():
print(id(a))
a = 1
t()
>>> runfile('C:/Users/Dave/data/Code/Python/lib/test.py', wdir='C:/Users/Dave/data/Code/Python/lib')
xx
>>> a = 999
>>> print(id(a))
yy
>>> t()
xx
This is the default behavior of runfile. It run the code in different namespaces.
def runfile(filename=None, args=None, wdir=None, namespace=None, post_mortem=False, current_namespace=False):
Change the current_namespace to True if you want to run it in the current namespace.
This question already has answers here:
In Python, variables inside if conditions hide the global scope even if they are not executed?
(4 answers)
Closed 4 years ago.
Today I'm reading python change log and meet the nonlocal keyword and did some experiment with it. I find a confusing situation where untriggered assignment will change the nonlocal keyword behavior, please see the example below.
def a():
x = 'a'
def b():
def c():
nonlocal x
x = 'c'
c()
b()
print(x)
a()
>>> python3 test.py
c
def a():
x = 'a'
def b():
def c():
nonlocal x
x = 'c'
c()
if False:
x = 'b'
b()
print(x)
a()
>>> python3 test2.py
a
You can saw that in test2.py, there is an untriggered assginment x = 'b' which changed the behavior of nonlocal.
Why this happened?
Python decides which variables are local to a function at compile time. x is assigned to within the function b, so it's local. That that branch is never actually reached at runtime is irrelevant and can't be decided in general.
So the x in c that is nonlocal is the next x in an outer scope, namely the one in b.
The alternative would be much more surprising -- consider what would happen if the if False: was instead if rand(10) == 6:. Then during the first call of b the nonlocal variable would refer to the outermost one, but randomly at some later call of b it would start referring to the other one!
Sorry for the title, I hope it reflects correctly my problem :
In the following code, I was expecting the result to be result 0 1 2 but instead I have 2 2 2. The code inside my_function seems to be interpreted with the last instance of obj. What is wrong ?
class Example:
def __init__(self, x):
self.x = x
def get(self):
return self.x
a_list = []
for index in range(3):
obj = Example(index)
def my_function(x):
#some stuff with x like obj.another_function(x)
return obj.get()
a_list.append(my_function)
for c in a_list:
print(c())
When you define this
def my_function():
return obj.get()
Python will understand that my_function should run the get() method of an object called obj and return the value. It won't know the value of obj and what the get() method does until you attempt to call it.
So, you are actually defining three different functions that will eventually do the same thing. And, in the end, running the same code thrice.
But why is the return 2 2 2?
Because after the last iteration, the value of obj is Example(2)* because you redefine its value at every iteration, and the last one remains.
*
because of this line obj = Example(index)
Understanding a few things about how python works will help you understand what's happening here. Here obj is a closure, closures are evaluated at call time, not when the function is defined so if I do this:
x = "hello"
def printX():
print x
x = "goodbye"
printX() # goodbye
I get "goodbye" because printX is referencing a global variable in my module, which changes after I create printX.
What you want to do is create a function with a closure that references a specific object. The functional way to do this is to create a function that returns another function:
x = "hello"
def makePrintX(a):
def printX():
# We print a, the object passed to `makePrintX`
print a
return printX
# x is evaluated here when it is still "hello"
myPrintX = makePrintX(x)
x = "goodbye"
myPrintX() # "hello"
If you're having trouble understanding the above example I would recommend reading up on python's scoping rules. For your example, you could do something like this:
class Example:
def __init__(self, x):
self.x = x
def get(self):
return self.x
def makeObjFunction(obj):
def objFunction(x):
return obj.get()
return objFunction
a_list = []
for index in range(3):
obj = Example(index)
my_function = makeObjFunction(obj)
a_list.append(my_function)
for c in a_list:
print(c("some value"))
You are appending three my_functions to the a_list which are all closures over the same Example object. Try:
def my_function():
return obj
<__main__.Example object at 0x0054EDF0>
<__main__.Example object at 0x0054EDF0>
<__main__.Example object at 0x0054EDF0>
You can see they have the same id so calling get() on each should give the same answer.
If you just append the obj.get function (and drop the my_function) it'll work fine.
a_list.append(obj.get)
....
0
1
2
Edit: You've updated your question so to let you do more stuff in my_function(). It's still basically a scoping problem.
def my_func_factory(p_obj):
def my_function(x):
#some stuff with x like obj.another_function(x)
return p_obj.get()
return my_function
for index in range(3):
obj = Example(index)
a_list.append(my_func_factory(obj))
Since my_function can't see obj being reassigned, each instance doesn't pick up the change.
I think append() during the for just append the function address in a_list[]. After for iteration, the a_list is really given the number. Then it discovers the address of my_function, and they get the number in my_function, this is, 2. That's why you get [2,2,2].
Or maybe, in my_function, function give the method of "obj". But for iteration change the "obj" memory address each time, so the symbol "obj" always aim to the newest object Example. Due to my_function always get "obj", you get the same number from the last object.
I have write down a script that can be usable as both stand alone application or as a module that can be imported by another script. I have three function along with the main (a dummy code bellow explains my original condition):
script_first.py
def add(a,b):
c = a+b
return c
def mult(a,b):
c = a*b
return c
def main():
d = mult(4,5)
e = add(4,5)
print d,e
return d,e
if __name__=="__main__":
main()
script_second.py
import script_first
script_first.main()
Now if i run "script_first.py" or with "script_second.py" it return and print similar result.
My problem is that i want to do either "print d,e" if it runs as a stand alone script or " return d, e" if "script_first.py" runs from another script like "script_second.py"
how can i achieve this...
thanks
You could see if it is called by a module or standalone using if __name__ == '__main__': statement and add a check variable to check if to print or not
def add(a,b):
c = a+b
return c
def mult(a,b):
c = a*b
return c
def main(Check=False):
d = mult(4,5)
e = add(4,5)
if Check:
print d,e
else:
return d,e
if __name__ == '__main__':
TO_PRINT = True
dag=main(TO_PRINT)
I don't think you really want to not return some of the time. Having different behaviors (like returning or not) at different times can make things very confusing when it comes time to debug problems later on.
If you don't want the results to be printed when it's run from another module, move the print statement out of the function and into the if __name__ == "__main__" block (that is, print the returned values):
def main():
d = mult(4,5)
e = add(4,5)
return d,e
if __name__ == "__main__":
print main()
This doesn't quite do the right thing though, you'll get parentheses around the values printed, because the return value is a tuple and print (x, y) is not the same thing as print x, y in Python 2 (the comma doesn't really make a tuple in the second version, it's more magical).
Fixing this issue is a bit awkward. It's much easier in Python 3, where print is a function and you can unpack the returned tuple as you are calling it. If you're using a recent version of Python 2, you can get the nicer Python 3 behavior by putting from __future__ import print_function at the top of your module:
from __future__ import print_function
# function definitions as before
if __name__ == "__main__":
print(*main())
The * says "Unpack the results returned from main() as separate arguments to print.
You have already half done the work by using __name__ = '__main__' .
The __name__ variable will be set to '__main__' only when the script is run standalone, the __name__ would be set to module name, when the script gets imported in another script.
What you can do for you case is to maybe define two different functions, one which returns d,e and another which just prints it.
Call the one that prints inside the if __name__ = '__main__': block, if you want to be extra secure you can define the function only inside that block, so that when its imported as a script, the function to print is not even available.
Example -
def add(a,b):
c = a+b
return c
def mult(a,b):
c = a*b
return c
def main():
d = mult(4,5)
e = add(4,5)
return d,e
if __name__=="__main__":
def _main():
d, e = main()
print d, e
_main()
Example/Demo -
>>python a.py
20 9
>>python
>>> import a
>>> a._main()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute '_main'
>>> a.main()
(20, 9)