简体   繁体   中英

Referencing (as opposed to assigning to) global variables in Python functions. Bad practice or not?

There are plenty of posts on when global variables must be declared in Python, and relatedly, on Python scope rules. I haven't been able to find a satisfactory treatment of the more specific question above, however, either on the internet or in text books I've consulted.

Even as a beginner programmer, I can appreciate the potential difficulties that could arise from assigning to global names in a function, and why most programmers recommend that the global statement therefore be used sparingly.

However, many of my early programmes contain many functions which themselves contain numerous references (ie not requiring that global be declared) to global variables. It seems to me that, because these are just references (ie not changing the variable), there isn't the same potential for difficulties to arise as in the case of assigning to globals.

I'd appreciate if more experienced programmers could guide me as to the best practice of global references (as opposed to assignments) in functions. Should I change these global references to function arguments? Many thanks.

If you try to use a global variable inside of a function the interpreter will try to look for it in the nearest scope, then in others possible. If your code is complicated enough, it'll cycle through lots of scopes and lots of different variables trying to find the one you want. If your script only consists of some functions that do not use the global variable frequently it'll be OK.

All in all, the more complicated your code is, the more time will be spent just searching for the variable.

If you only need a reference to global state, consider passing that as an argument to the function instead of relying on kicking upward through scopes until you hit one where the global value is defined.

Under the assumption that the global state truly will only be referenced and never mutated, there's no good reason not to just pass it as an argument whenever a function needs it. (If the global value is a large data structure itself, you should be passing it around by reference anyway).

Usually, this still results in a confused design, because you will start to pass the state argument as a parameter all over the place. For example, if a function calls some other function and that interior function needs the global state, then so does the outer function. "Solving" this by having the interior function just kick upward through scopes doesn't really reduce any of the dependence, since the outer function still needs to be nested within scopes that eventually result in finding the global variable. So why not at least do a favor for future code readers and make the use of the variable explicit by naming it in the argument list for the function?

First of all, there's little wrong with module-level global constants, provided that they're actually constant. If the math module didn't provide pi , I wouldn't fault you for defining it at the top of your module rather than passing it as an argument to any function that needed it. The style guide suggests that you capitalize the variable name in these cases. This is a signal that these variables should not be assigned to.

On the other hand, it's rare that I actually use such constants in my code. As @prpl.mnky.dshwshr suggests, favor passing variables as arguments to the functions that use them. If you keep passing the same combination of arguments, such as in:

def f1(foo, bar, baz, x):
    ...

def f2(foo, bar, baz, y):
    ...

def f3(foo, bar, baz, z):
    ...

it might suggest that f1 , f2 , and f3 should be in a class encapsulating the values of foo , bar , and baz :

class MyClass:
    def __init__(self, foo, bar, baz):
        self.foo = foo
        self.bar = bar
        self.baz = baz

    def f1(self, x):
        ...

    def f2(self, x):
            ...

    def f3(self, x):
            ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM