Python functions: Pass global variables if only accessing them? - python

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.

Related

when should I make a function that has parameters / arguments?

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.

Is it idiomatic to take advantage of python's pass-by-sharing of mutable data structures like lists?

I know that in Python, because it's pass-by-sharing, if I pass a mutable object (like a list) to a function, and then use that function to mutate it, I don't need to explicitly pass it back, because the caller can see the changes:
def add_to_list(list_of_nums):
list_of_nums.append(26)
my_list = [12]
add_to_list(my_list)
print my_list # >>>[12, 26]
So this works. But is it a good idea/good python practice? My gut says it's not (the same way global variables are almost always a bad idea), but maybe that's just because I first learned C++ in all its pass-by-value glory.
And yes, I know that I can code my way around this (say by creating a class), but the question is, should I, or is this generally seen as acceptable practice?
I think whether or not this is "acceptable" will be determined by the context and how well the function is named. keep Pep 20 in mind: "Explicit is better than implicit."
Python fully supports functional programming, and in that case, modifying objects that are passed in is often expected. If the function is named appropriately and documented well, I think it's fine. Your example illustrates this pretty well. The function is called add_to_list, which pretty explicitly says what the function does.
If your program/script takes more of an object-oriented approach, modifying passed-in objects should be replaced by creating the appropriate classes instead, like the native list class in your example - it has an append() method that modifies the list instead of passing the list into a separate function.
The key is to be consistent with your paradigm and well documented. If you cover both of those bases, I think it's acceptable.

Making all variables global

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.

Python: Using a dummy class to pass variable names?

This is a followup to function that returns a dict whose keys are the names of the input arguments, which I learned many things (paraphrased):
Python objects, on the whole, don't know their names.
No, this is not possible in general with *args. You'll have to use keyword arguments
When the number of arguments is fixed, you can do this with locals
Using globals(). This will only work if the values are unique in the module scope, so it's fragile
You're probably better off not doing this anyway and rethinking the problem.
The first point highlighting my fundamental misunderstanding of Python variables. The responses were very pedagogic and nearly instantaneous, clearly this is both a well-understood yet easily confused topic.
Since I'd like to learn how to do things proper, is it considered bad practice to create a dummy class to simply hold the variables with names attached to them?
class system: pass
S = system ()
S.T = 1.0
S.N = 20
S.L = 10
print vars(S)
This accomplishes my original intent, but I'm left wondering if there is something I'm not considering that can bite me later.
I do it as a homage to Javascript, where you don't have any distinction between dictionaries and instance variables. I think it's not necessarily an antipattern, also because differently from dictionaries, if you don't have the value it raises AttributeError instead of KeyError, and it is easier to spot typos of the name. As I said, not an antipattern, provided that
the scope of the class is restricted to a very specific usage
the routine or method you are calling (e.g. vars in your example) is private in nature. I would not want a public interface with that calling semantics, nor I want it as a returned entity
the name of the "dummy" class is extremely clear in its intent and the kind of aggregate it represents.
the lifetime of that object is short and uneventful. It is just a temporary bag of data.
If these constraints are not respected, go for a fully recognized class with properties.
you can do that, but why not use a dictionary?
but if you do that, you're better off passing keywords args to the class's constructor, and then let the constructor copy them to the app's members. something like:
class Foo(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)

Arguments, local variables, and global variables coding convention in Python

In python, there is no way to differentiate between arguments, local variables, and global variables. The easy way to do so might be have some coding convention such as
Global variables start with _ and capital letter
arguments end with with _
_Gvariable = 10
def hello(x_, y_):
z = x_ + y_
Is this a Pythonian way to go? I mean, is there well established/agreed coding-standards to differentiate them in python?
=== ADDED ===
I just want to discriminate between arguments and local variables. As arguments are given from outside, and more like a ROM in the sense that it is not assumed to be read only.
C++ provides the const keyword to prevent the arguments from changing, but not for python. I thought appending _ can be one of a way to mimic this feature in python.
I would do all your python programming according to PEP 8 guidelines. Anyone who has to read your code will thank you for it.
http://www.python.org/dev/peps/pep-0008/
Why is there a need to distinguish between arguments and local variables, since one is merely a subset of the other. You can use locals(), globals(), and vars() to view scope if you are having local-global issues. The inspect module can help with that, too. And if possible, avoid using global variables as much as possible.
It is usually obvious in python which variables are local and which are global, since to modify a global variable you have to declare it using the the global keyword at the start of a function. However I sometimes add a global declaration even if it is not necessary for python to compile it, in order to emphasize that an object is global - e.g. modifying a mutable global data-structure.
Arguments should be obvious because they are in the function declaration.
As others have said constants should be in UPPER_CASE_WITH_UNDERSCORES, which is a convention shared by many languages.
If you find that you are having trouble keeping track of which are global, local and parameter variables I suggest that the problem may be your functions are too long and doing too much. Functions & methods should be short and do exactly one thing. I start to get the refactoring itch if my functions go over about 10-20 lines of code.
I recommend reading the book Clean Code by Robert Martin. The examples are in Java, but the principles apply to all languages.
That's absolutly awful. There is no reason whatsoever to use a special naming scheme for global and local objects. Also you should avoid having global objects unless they are functions, classes or constants.
Names for constants should be uppercase and seperated with underscores LIKE_THIS, class names look LikeThis and functions and method names should look like any other name. Names for objects which are implementation specific, can be changed/removed at any time or can not be relied on for any other good reasons should be prefixed with an underscore.
You should also read the Python styleguide PEP 8 which covers these and more style-related rules you should follow as long as it doesn't make your code less readable. Most Python projects follow this or at least a compatible version of this style guide.
Local variables are variables that are declared inside a function.
Global variables are variables that are declared outside a function.
For Example:
global_var = 5 #Global Variable
def add(a,b):
local_var = a+b #Local Variable
print("The sum is",local_var)
print("The global variable is",global_var)
add(10,20)

Categories

Resources