I am trying to write a program with python functions. The variables used in one function will be needed in various other functions.
I have declared it as global in the first function, then used the returned value in the second function. However in the third function, I would like to use the updated value from the second, but I am only able to get the values from the first function.
def func():
global val, val2
val = 3
val2 = 4
return val, val2
def func1(val, val2):
val = val + 1
val2 = val2 + 1
return val, val2
def func2(val,val2):
val = val + 1
val2 = val2 + 1
print val, val2
func()
func1(val, val2)
func2(val, val2)
I would like to get 5,6 as the answer, but am getting 4,5.
Assign the return values of your functions to val and val2.
val, val2 = func()
val, val2 = func1(val, val2)
func2(val, val2)
If the variable is declared as a function argument, it's a local variable for this function. In Your case if You declare def func1(val,val2): then val,val2 will both be local in function func1. If You want to use global variables do it like that:
def func():
global val,val2
val=3
val2=4
return val,val2
def func1():
global val,val2
val=val+1
val2=val2+1
return val,val2
def func2():
global val,val2
val=val+1
val2=val2+1
print val,val2
func()
func1()
func2()
returns:
5 6
But I think that using global variables should be avoided if using them is not necessary (check Why are global variables evil?). Consider using return the right way like in pp_'s answer.
Related
In the code below, I was getting this.
NameError: name 'digitsum' is not defined
Please note that we can return values but that's not I want exactly here. I just want to change the outside values inside function f.
class Solution:
def compute(n) -> int:
digitsum = 0
def f(k):
global digitsum
if k==0:
return
digitsum+=k%10
f(k//10)
f(3648)
return digitsum
In this case digitsum is not a global variable, which is why you're getting a NameError. In this particular case what you want instead is nonlocal.
A simplified example:
>>> def foo():
... x = 0
... def f():
... nonlocal x
... x += 1
... f()
... print(x)
...
>>> foo()
1
class Solution:
digitsum = 0
def compute(self,n) -> int:
self.digitsum = 0
def f(k):
if k==0:
return
self.digitsum+=k%10
f(k//10)
f(n)
return self.digitsum
Solution().compute(45)
I have a list of functions and need to call a function, if that function exists in that list. Also, I need to call the function with a string.
I have tried doing something like this:
if "func1" in funcs:
funcs.__getitem__("func1")
but I can't get it right
funcs = [func1, func2, func3]
def func1: return 1
def func2: return 2
def func3: return 3
if "func1" in funcs:
# call func1 since it exists
I expect the output to be 1, but I don't know how to call the function.
Also, this is not a duplicate because I won't call the function from a class.
Found out that I'll just use a dictionary instead. Much easier.
funcs = {"func1": func1, etc..}
def func1(): return 1
def etc..
if "func1" in funcs:
funcs["funcs1"]()
You can also use the class structure and the inspect module which might provide a bit more flexibility:
import inspect
class funcs:
def func1(): return 1
def func2(): return 2
def func3(): return 3
listfuncs = inspect.getmembers(funcs, lambda a:inspect.isfunction(a))
print(listfuncs)
listfuncs will be a list of tuples with function names and object reference.
Just improvising on the answer already provided by #Gwang-Jin Kim.
What happens if you do it this way?
def func1():
return 1
def func2():
return 2
tuple_list = [("func1",func1), ("func2", func2)]
if any([items[0] == "func1" for items in tuple_list]):
print("Do Something")
or this
for key, val in tuple_list:
if key == "func1":
print(val())
Also, it seems like a repeated question of call list of function using list comprehension
Gwang-Jin Kim is right in the fact that Python is interpreted; therefore, you functions needs to be defined before they are called. Now, you need to call a function when the user types the name of that function. It is possible to run the text that the user types with the eval() function; however, that is not recommended, because one cannot be sure of what the user will type in, which could result in unwanted errors.
Instead I recommend that you use a command system, where you call a function based on a predefined name, like shown:
def func1():
print(1)
def func2():
print(2)
while True:
try:
msg = input('Which function would you like to call?: ')
if not msg:
break
if msg.startswith('func1'):
func1()
if msg.startswith('func2'):
func2()
except Exception as e:
print(e)
break
def func1(): return 1
def func2(): return 2
def func3(): return 3
funcs = [func1, func2, func3]
funcs_dict = {f.__name__: f for f in funcs}
funcname = "func1"
funcs_dict[funcname]()
This checks - if functionname is under the functions name in funcs, then executes it!
(One can use dictionaries in Python to avoid if-checkings).
In case, that there are not such a list like funcs given, one has to do it using globals():
if callable(globals()[funcname]):
print(globals()[funcname]())
if callable(eval(funcname)):
print(eval(funcname)())
or:
try:
print(eval(funcname)())
except:
print("No such functionname: {}".format(funcname))
or:
try:
globals()[funcname]()
except:
print("No such functionname: {}".format(funcname))
I am new to python and trying to update a variable, say x, in an imported module and then trying to use the updated variable x in other variable, say y, but y uses the old value of x instead of the new value. Please help provide some pointers to make it work!
My intention is to use a py file to list all global variable which I can use them in other py files. I could update a global variable and use it but not sure how to use an updated global variable in other variables.
Sample code:
a.py:
var1 = 0
var2 = var1 + 1
b.py:
import a
def update_var():
a.var1 = 10
print("Updated var1 is {}".format(a.var1))
print("var2 is {}".format(a.var2))
if __name__ == "__main__":
update_var()
Output:
Updated var1 is 10
var2 is 1
Expected Output:
Since i am updating var1 to 10, i am expecting that the updated value be used in var2
Updated var1 is 10
var2 is 11
Python doesn't work that way. When you import a module, the code in the module is executed. In your case, that means two variables are defined: a.var1 with value 0 and a.var2 with value 1. If you then modify a.var1, you won't affect a.var2, its value was defined when you imported the module and it won't change unless you explicitly alter it.
This is due to var2 being initialized only once whilst importing.
The way around this would be to write a getter or and update function.
A possible getter function would be:
a.py
var1 = 0
var2 = var1 + 1
def getVar2():
return var1 + 1
b.py:
import a
def update_var():
a.var1 = 10
print("Updated var1 is {}".format(a.var1))
print("var2 is {}".format(a.getVar2()))
if __name__ == "__main__":
update_var()
A possible update function would be:
a.py
var1 = 0
var2 = var1 + 1
def updateVar2():
var2 = var1+1
b.py:
import a
def update_var():
a.var1 = 10
a.updateVar2()
print("Updated var1 is {}".format(a.var1))
print("var2 is {}".format(a.var2()))
if __name__ == "__main__":
update_var()
Based on the inputs from #GPhilo and my personal experiences i came up with below working solutions, guess solution 2 is more pythonic.
Solution 1:
a.py:
class Globals:
def __init__(self, value):
self.var1 = value
self.var2 = self.var1 + 1
b.py:
from a import Globals
def update_var():
globals_instance = Globals(10)
print("Updated var1 is {}".format(globals_instance.var1))
print("var2 is {}".format(globals_instance.var2))
if __name__ == "__main__":
update_var()
Output:
Updated var1 is 10
var2 is 11
Solution 2:
Change implementation of a.py as below"
a.py:
class Globals:
def __init__(self, value):
self._var1 = value
self.var2 = self._var1 + 1
#property
def var1(self):
return self._var1
#var1.setter
def var1(self, value):
self._var1 = value
Could I set a variable inside a function scope, knowing that I sent this variable like a parameter..
See the example:
def test(param):
param = 3
var = 5
test(var)
print var
I want the value printed be 3, but it doesn't happen.
How can I do that?
Thanks..
You can return the value of param like this:
def test(param)
param = 3
return param
var = 5
var = test(var)
Or you can use a global variable.
Better to use return than a global:
def test(param):
param = 3
return param
var = 5
var = test(var)
print var
The global statement allows you to assign to variables declared outside a function's scope.
var = 5
def test():
global var
var = 3
test()
print var
However, I have found that I seldom need to use this technique. The functional programming model makes this less important.
Let's say we have a module m:
var = None
def get_var():
return var
def set_var(v):
var = v
This will not work as expected, because set_var() will not store v in the module-wide var. It will create a local variable var instead.
So I need a way of referring the module m from within set_var(), which itself is a member of module m. How should I do this?
def set_var(v):
global var
var = v
The global keyword will allow you to change global variables from within in a function.
As Jeffrey Aylesworth's answer shows, you don't actually need a reference to the local module to achieve the OP's aim. The global keyword can achieve this aim.
However for the sake of answering the OP title, How to refer to the local module in Python?:
import sys
var = None
def set_var(v):
sys.modules[__name__].var = v
def get_var():
return var
As a follow up to Jeffrey's answer, I would like to add that, in Python 3, you can more generally access a variable from the closest enclosing scope:
def set_local_var():
var = None
def set_var(v):
nonlocal var
var = v
return (var, set_var)
# Test:
(my_var, my_set) = set_local_var()
print my_var # None
my_set(3)
print my_var # Should now be 3
(Caveat: I have not tested this, as I don't have Python 3.)