-1

I have a function that gets the user's preferred directory for use in many other functions:

def get_pref():
    q1 = "What is your pref. dir.?"
    path = input(q1)
    ...
    return path

Then, the path is used to specify locations in numerous functions (only 2 are shown here.)

Option A:

def do_stuff1():
    thing = path + file_name  # using global path variable
     ...

def do_stuff2():
    thing = path + file_name  # using global path variable
    ...

path = get_pref()
do_stuff1()
do_stuff2()

Option B:

def do_stuff1(path_):
    thing = path_ + file_name  # accepts path as argument
    ...

def do_stuff2(path_):
    thing = path_ + file_name  # accepts path as argument
    ...

path = get_pref()
do_stuff1(path)
do_stuff2(path)

Option A accesses the global variable path in each function. Option B accepts the path as an argument in each function.

B seems to be repetitive since the same variable is passed each time, but I know globals are strongly discouraged in Python. Would it be acceptable to declare the path as a global constant, or is there a more conventional way?

martineau
  • 119,623
  • 25
  • 170
  • 301
funyuns
  • 229
  • 1
  • 9
  • I use them, mainly for log data. It is frowned upon though. – MVB76 Aug 17 '20 at 23:23
  • 1
    The various positions on using global variables are readily available with an on-line search. We expect you to include this research as part of your post. – Prune Aug 17 '20 at 23:29
  • [Global Variables Are Bad](http://wiki.c2.com/?GlobalVariablesAreBad) and [Global Variables are Considered Harmful](http://wiki.c2.com/?GlobalVariablesConsideredHarmful), so avoid them as much as possible. – martineau Aug 17 '20 at 23:36
  • Python doesn't have globals. It has variables in the module's namespace. They can't leak into other modules by accident. So it troubles me that when this question crops up, it tends to use python as an example. Don't mutate globals. Avoid using [the `global` _keyword_](https://stackoverflow.com/q/4693120/418413) and avoid changing the contents of global dictionaries and lists and you will avoid most of the pitfalls of globals in Python. – kojiro Aug 18 '20 at 02:18

5 Answers5

3

If you are writing a short script, you shouldn't be afraid to use globals. Globals are discouraged due to the namespace pollution and lack of modularity. However, if you have a short script, they will not be a significant impact to maintainability.

However, if you are producing a larger module, consider making a class out of your related functions and maintain the path as an instance variable. You may even consider passing the path into the constructor of your instance variable to make it clear to other engineers that the functionality of the class depends heavily on the path value. A setter and getter would also be recommended for this class attribute.

Mark
  • 4,249
  • 1
  • 18
  • 27
  • 2
    my opinionated tldr make it work first, then move your globals out, don't leave globals in a large code base, wrapping common functionality into classes is one way to help when your code base moves beyond one thing – kyle Aug 17 '20 at 23:47
2

I prefer B) because I generally find it makes code easier to read and reason about.

You're right though. Strict adherence to this means that every dependency that a function needs must be not only passed as arguments to that function, but must also be passed to every parent function up the call chain. This can complicate code; even if it does make clearer the "pipes of information" that are involved.

In this case though, I think A) is acceptable for a couple reasons:

  • The data involved is immutable, so you know it can't change out from under you at odd times.

  • It seems like you're also only assigning it once, so you don't need to worry later about the reference changing either.

The key that I've always kept in mind is: globals are not inherently evil. Global, mutable states can be though because it's background information that you can't easily see, but potentially affects the operations of tests and other functions. As long as global states aren't changing (either as a result of mutating the object, or the reference itself through reassignment), I personally don't have any issue with globals.

Carcigenicate
  • 43,494
  • 9
  • 68
  • 117
  • 1
    Kudos for "globals are not inherently evil". Other than cats, you can pretty much substitute anything for globals in that sentence :-) People should realise *why* some things are frowned upon, then they'd better understand the exceptions. – paxdiablo Aug 18 '20 at 00:11
0

If you have data and functionality which necessarily interoperate, consider wrapping it in a class. The "path" can be stored as a variable in the class.

import os

class MyClass(object):
    def __init__(self, path):
        self.path = path

    def my_func(self):
        thing = os.path.join(path, "foo")
Charles Angus
  • 394
  • 1
  • 7
0

You can use a class to store your "global" like this, which is like a compromise between A and B.

# dc = data container
class dc():
    def __init__(self):
        self.path = "aaa-"

def do_stuff1(dc_object, file_name):
    dc_object.path = dc_object.path + file_name
    
Obj = dc()
do_stuff1(Obj, "test")

print(Obj.path)
#out: aaa-test
Andreas
  • 8,694
  • 3
  • 14
  • 38
  • I'm not *entirely* convinced that simply wrapping a your globals up in a global class instance makes them any less global :-) – paxdiablo Aug 17 '20 at 23:59
-3

As a beginning programmer, you should avoid globals as much as possible, until you gain the experience to know when they're acceptable.

Option B is clean code, you should pass it as an argument to a function. And no, it is no repetitive code :)

  • "***Never*** do X" is almost *invariably* the wrong advice, especially since you offer no support as to why. That's because just about every rule has an exception. – paxdiablo Aug 18 '20 at 00:01
  • The exceptions are valid to experienced coders :) Unfortunately, python makes it easy to exploit and use globals all over... bad habbit... "Never" would go to the scope of this question and it would be a good habbit not to use... Exceptions are valid, agree :) – Antonis Adamakos Aug 18 '20 at 00:15
  • 2
    Then you may want to consider rewording your advice to something like "As a beginning programmer, you should avoid globals as much as possible, until you gain the experience to know when they're acceptable", since that is, after all, what you seem to be stating in your clarification. – paxdiablo Aug 18 '20 at 00:22