I have a function in my Python script where multiple variables are created, and I want to use them in other functions. I thought of using global for this but I thought it would be the incorrect way to do so.
So can anyone tell me what would be the best way to create variables in a function for other functions?
Organize the variables into a class. Instantiate the class in one function and then pass the instance to wherever you need it.
Rule of thumb: If making something global seems like a good solution at some point, don't do it. There is always a better way.
You could create a "namespace" object -- an object which functions as a namespace for the purpose of keeping your global namespace clear:
class namespace():
pass
global_data=namespace()
def add_attributes(obj):
obj.foo="bar"
add_attributes(global_data)
print (global_data.foo) #prints "bar"
However, this is only marginally better than using the global keyword. You really do want a class here as mentioned by Paul.
Declare the variables as attributes of the function.
def f1():
f1.a=100
f2.b=200
def f2():
print(f1.a,f2.b)
f1()
f2()
output:
100 200
This might be a good place to implement a class. This has lots of advantages. See Classes in the tutorials.
Related
Does anyone know how to call a child function that belongs to a parent function using the dot operator, but where the child function's name is stored in a string variable.
def parent_function():
# do something
def child_function():
# do something else
Now imagine I have a string called 'child_function'. Is there a way to do this:
method_name = 'child_function'
parent_function.method_name()
I understand that method_name is a string and so it is not callable. The syntax above is clearly wrong, but I wanted to know if there was a way to do this?
Thank you!
As others have pointed out in comments there will need to be a little more setup to actually call an inner function, such as a parameter like this:
def parent_function(should_call=False):
# do something
def child_function():
print("I'm the child")
if should_call:
child_function()
That being said, and to answer your specific question, you technically can call the inner function directly. I should note this is bad and you should not be doing this. You can access the inner function via the outer function's code object
exec(parent_function.__code__.co_consts[1])
As opposed to many comments, you can actually access inner functions even if the outer function is not in the system memory anymore. This technique in python is called closure.
To know more about closure, visit Programiz
Coming to your requirement, you need to call the nested method outside the nesting function.
What are we leveraging?
Closure technique of python
locals() method which returns all the local properties and methods inside an enclosing method.
lambda x: x, A anonymous (Lambda) function
def parent_function():
# do something
def child_function():
# do something else
print("child_function got invoked")
return {i: j for i, j in locals().items() if type(j) == type(lambda x: x)}
# locals() returns all the properties and nested methods inside an enclosing method.
# We are filtering out only the methods / funtions and not properties / variables
parent_function()["child_function"]()
The below is the output.
>>> child_function got invoked
Better Solution:
Instead of using nested methods, leverage the concept of classes provided by Python.
Enclose the nested functions as methods inside a class.
If you include global child_function in parent_function, then once you run parent_function, you can call child_function in the main program. It's not a very clean way of defining functions, though. If you want a function defined in the main program, then you should define it in the main program.
Consider the following case:
def parent_function():
a = 1
Can you access a from the global scope? No, because it is a local variable. It is only existent while parent_function runs, and forgotten after.
Now, in python, a function is stored in a variable just like any other value. child_function is a local variable just like a. Thus, it is in principle not possible to access it from outside parent_function.
Edit: unless you make it available to the outside somehow, e.g. by returning it. But then, still the name child_function is internal to parent_function.
Edit 2: You can get functions given by name (as string) by using the locals() and globals() dictionaries.
def my_function():
print "my function!"
func_name = "my_function"
f = globals()[func_name]
f()
when should we actually create a function that has parameters / arguments?
today I made a programming project. Then it occurred to me when should I actually create a function that has parameters .. I usually create it when there is a global value / variable and that value must exist in some function then I make that value the argument of the function .. did I do it right? or wrong? if wrong what are the best practices for doing it?
varGlobal = "test"
def foo():
print(varGlobal)
# or
def foo(parm):
print(parm) # parm -> varGlobal
def foo():
ask = input("ask")
print(ask)
# or
def foo(parm):
print(parm) # parm -> global user input
It's usually a good idea to use parameters. Consider what the purpose of the function is. Parameterized functions are more generally useful than non-parameterized functions.
If the first case, is whatever foo does applicable only to a single value, or could it be useful for arbitrary values, regardless of what variable might refer to them? In the former case, you are stuck using varGlobal. In the latter, the call can always use foo(varGlobal) if that's the necessary argument.
In the second, might foo be useful to someone who already has a value, and doens't need to call input? In the former case, you are stuck calling input. In the latter, the caller can always use foo(input()) or the like if they really need to call input.
I would strongly suggest that you should use parameters and arguments in every function. it simply makes the whole process of design simpler.
You can clear see what data the function uses, and what it returns.
The only use of global values (either module globals, or globals imported from other modules are :
Module or application wide constants
Module or application wide function or classes (which are in Python efectively module level 'globals'.
Your functions should always return values and never change a global value (by definition if you stick to the above list that you wont be changing anything).
In my opinon using the 'global' keyword is never needed (in 8 years of coding I have never needed it, or identified a reason to use it).
Using global variables is bad practice in any language GlobalVariablesAreBad
Global variables can be used if you need to access or modify the variable in several methods/classes in the same module.
Remember you need to point global my_global_variable to modify the variable.
Parameters are variables needed in the method to do the processing. These variables should live locally in the method. If you need to retrieve something from the method, you should add a return statement. Also, if you need to return several variables you can return as tuple.
So, in this way, you're organizing your code, making all variables visible to other people. Also I recommend you to use docstrings to fully document your methods, variables and processing.
When we need to solve the same sort of question but with different arguments. So you don't have to write the same function over and over again. Let's say you want to write a function that will return the square of the provided number as an argument.
So you write
def square(num):
return num*num
So every time you need to have square of a number..you just put that number in place of the argument and not write the whole function again.
I'm relatively new to thinking of python in terms of object-oriented programming, and it's coming relatively slowly to me.
Is it possible to pass global variables between classes with multiple functions in them? I've read extensively about them here and in other sources, but I'm still a bit confused.
My ultimate goal is to define a variable globally, assign it a value in a function of one class, and then USE it in another class's function. Is that possible? I'm building a pythonaddin for ArcMap, which requires a class for each button. I want to have a button to assign a value to a variable, and then use that variable in another class in the script.
(Before I get the flak, I know it's relatively bad form to use global variables in the first place, I'm trying to learn)
For instance, as a highly simplified example:
x = []
class A():
def func_1(self):
#populate the x variable
global x
x = 1
class B():
def func_2(self):
global x
#do stuff with x
Is this acceptable (even if not pythonic)?
Yes, it can work. Here is the modified code:
x = []
class A:
def func_1(self):
#populate the x variable
global x
x.append(1)
class B:
def func_2(self):
global x
print x
a = A()
a.func_1()
b = B()
b.func_2()
It can print the list x correctly. When it's possible, you should try to avoid global variables. You can use many other ways to pass variables between classes more safely and efficiently.
PS: Notice the parameters in the functions.
A more Pythonic solution would be to have the button objects (in their method that handles the "press" event) set an attribute or call a method of whatever object needs the information.
Yes, it is possible. Your code is almost right, just missing a couple of parenthesis in the function definitions. Other than that, it works.
Now, is that acceptable? In 99% of cases, no, it's not. There're many ways of passing variables and sharing data between classes, and using global variables is one of the worse ones, if not the worst.
I know that I can add a variable to the global namespace "by name" with something like:
def getNewVar(name,val):
globals()[name]=val
The things is, I would like to do this in a local namespace. I have already tried and failed in using locals() instead of globals(). Someone probably wants to know why I would do something like this. OK, in my use case, the argument to the function is actually a dictionary, and I would like to do something like:
def processDictEntries(dict):
for varname in dict.keys():
locals()[varname]=dict[varname] # won't work, of course
This way, further down in the function, I won't have to keep typing
result1=dict['var1']+5.
result2=dict['var2']*dict['var7']
over and over again. I can just type
result1=var1+5
result2=var2*var7
And, if there is a way to do this in a small loop like I have written, then I don't have to do:
var1=dict['var1']
var2=dict['var2'] etc.
either. I'm really just looking for economy of code; it's a big dictionary.
BTW, the entries of the dictionary are never altered; it is strictly input. And, yes, I know that if the input dictionary lacks one of the variables the function needs, I will be in touble, but I think that can be dealt with. Thanks!
If you can change how you call the function:
def processDictEntries(var1=None,var2=None,**kwargs):
#do stuff with var1,var2 ...
And then call the function as:
processDictEntries(**dict)
and of course, if you can't do that, you can always use processDictEntries as a wrapper:
def _processDictEntries(var1=None,var2=None,**kwargs):
...
def processDictEntries(d):
return _processDictEntries(**d)
As a side note, it's not a good idea to name a variable dict as then you shadow the builtin function
I'm trying to get a sense of best practices in python. If I define a function to access (but not change) a global variable, it's not generally necessary to specify the variable as global in the function. But is it faster to pass the global variable to the function? I ask because I've come across some references to the cost of looking up global variables, but I'm not sure that I understand. For example:
def f1(localList):
for element in localList:
if element in globalSet:
pass #do stuff.
def f2(localList, localSet):
for element in localList:
if element in localSet:
pass #do stuff.
globalList = <arbitrary list>
globalSet = <arbitrary set>
f1(globalList)
f2(globalList, globalSet)
is f2 generally considered to be the faster/better/more "pythonic" approach compared to f1?
If globalList and globalSet data is tightly bound to the functions i'd use a class and define those lists as class propierties and those functions as staticmethods (or instance methods, whatever i need)
Global variables are generally considered bad practice in programming in general. Basically because any code that can see the variable can change it. Especially in multithreaded programs this can be a source of bugs.
You should think of Python variables as names for, or references to objects. So passing a variable to a function isn't costly.
Using Globals is always a bad design choice. In any case you can always come up with a solution which would be more Pythonic by not using Globals.
If you have to share lot of variables between functions, you can
reconsider an OO approach.
If you have to pass many parameter's to a
functions, you can opt for varargs or kargs.
Remember, parameters are passed by reference so there is no efficiency lost.
----Special cases aren't special enough to break the rules.