Python 3: Assign with Exec [duplicate] - python

This question already has an answer here:
Eval/Exec with assigning variable - Python
(1 answer)
Closed 3 years ago.
First of all, yes I know what I'm doing is bad. It's part of a hacky project that I'm trying for fun.
In Python 2.7, you could do this:
def myfunc():
exec('a=3')
print('Result: a = {}'.format(a))
myfunc()
And get Result: a = 3
Not so in Python 3.6, where you'll get NameError: name 'a' is not defined.
I can try to work around this by doing:
def myfunc():
exec('globals()["a"]=3')
print('Result: a = {}'.format(a))
myfunc()
Which in Python 3.6 gives the desired Result: a = 3 (and yes, has dangerous consequences by modifying globals). But of course it fails in the following case:
def myfunc():
a=2
exec('globals()["a"]=3')
print('Result: a = {}'.format(a))
myfunc()
Where I get Result: a = 2. Swapping in exec('a=3') here will also give Result: a = 2.
Question: Is there any hack in Python 3 that effectively allows me to assign to a variable in a function body?

def myfunc():
exec('a=3', locals(), globals())
print('Result: a = {}'.format(a))
myfunc()

Related

In Python 3.0 a function returns none because a function does not store it’s output unless we use a return statement?

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

Why does Spyder not pick up a global variable? [duplicate]

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.

How do you create new commands in Python when immutable data types are involved? [duplicate]

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 5 years ago.
In Python, the following code prints '0', not '1'.
def inc(x):
x = x+1
a = 0
inc(a)
print(a)
I understand why this happens; it's because integers are immutable. What I don't understand is how to get around this behaviour when it's undesirable. Suppose we want to create a new command such that the code
a = 0
inc(a)
print(a)
prints '1'.
Obviously, the naive approach won't do it. What can we do instead?
Similar (a bit more general) question can be found here along with a discussion how Python passes params to functions. In short, without making x variable in your code an object, I believe there's nothing we can do. Of course, you can alter your code to e.g. return changed value from function inc() and print that (i.e. print(inc(x))) or just do the printing from inside the inc() method, but that's not what you're essentially looking for.
If I understand correctly, You are trying to increment variable a using function inc(var) and passing 'a' as a external variable to the function inc().
As #Marko Andrijevic stated, variable x passed to function inc() and variable x defined in the function are different . One way to achieve is by returning value of x and collecting externally, which you may not be looking for.
Alternately, Since you have defined variable 'a' outside function ,it can be called global variable.
If you want to pass that to a function, and manipulate it, you need to define that variable ('a' in your case) inside the function as global. Something like below.
def inc(x):
global a
a = x+1
Now when the new value assigned to 'a' after 'x+1', it is retained after execution of 'inc(x)'
>>> a = 0
>>> inc(a)
>>> a
1
EDIT -1
As per comments by #DYZ . Its correct. declaring global a inside inc() function will always increment a.
A better alternative will be , in that case, to return x inside inc() and assign that value to any external variable.
Not an elegant solution, but works as intended.
def inc(x):
return x+1
Result
>>> a
0
>>> a = inc(a)
>>> a
1
>>> a = inc(a)
>>> a
2
>>> b = 0
>>> b = inc(b)
>>> b
1
>>> a
2
>>>
one can use yield to get variable values.
def inc(x,y,z):
x += 1
y+=1
z+=1
yield x,y,z #inc doesn't stop
yield x+y+z
a=b=c=0
gen=inc(a,b,c)
gen=list(gen)
a,b,c,sum=gen[0]+(gen[1],) #however, index must still be known
print a,b,c,sum

Python Call Function from String [duplicate]

This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 8 years ago.
s = "func"
Now suppose there is function called func.
How can i call in Python 2.7 call func when the function name is given as a string?
The safest way to do this:
In [492]: def fun():
.....: print("Yep, I was called")
.....:
In [493]: locals()['fun']()
Yep, I was called
Depending on the context you might want to use globals() instead.
Alternatively you might want to setup something like this:
def spam():
print("spam spam spam spam spam on eggs")
def voom():
print("four million volts")
def flesh_wound():
print("'Tis but a scratch")
functions = {'spam': spam,
'voom': voom,
'something completely different': flesh_wound,
}
try:
functions[raw_input("What function should I call?")]()
except KeyError:
print("I'm sorry, I don't know that function")
You can also pass arguments into your function a la:
def knights_who_say(saying):
print("We are the knights who say {}".format(saying))
functions['knights_who_say'] = knights_who_say
function = raw_input("What is your function? ")
if function == 'knights_who_say':
saying = raw_input("What is your saying? ")
functions[function](saying)
else:
functions[function]()
def func():
print("hello")
s = "func"
eval(s)()
In [7]: s = "func"
In [8]: eval(s)()
hello
Not recommended! Just showing you how.
you could use exec. Not recommended but doable.
s = "func()"
exec s
You can execute a function by passing a string:
exec(s + '()')

How to get a closure to refer to the value that a variable had at the time of its definition [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Creating lambda inside a loop
In the code below, invoking any member of the returned array of closures
prints the number 4.
def go():
x = []
for i in range(5):
def y(): print i
x.append(y)
return x
I would like each member of the closure to print the number that i was when the closure was defined.
One way around this is to use default arguments:
def y(i=i):
print i
Default arguments are evaluated when the function is created, not called, so this works as you'd expect.
>>> i = 1
>>> def y(i=i): print i
...
>>> i = 2
>>> y()
1
A little extra info just for fun:
If you're curious what the defaults are, you can always inspect that with the .func_defaults attribute (__defaults__ in python3.x):
>>> y.func_defaults
(1,)
This attribute is also writeable, so you can in fact change the defaults after the function is created by putting a new tuple in there.

Categories

Resources