简体   繁体   English

在Python函数中引用(相对于分配)全局变量。 坏习惯与否?

[英]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. 关于何时必须在Python中以及在Python作用域规则上必须声明全局变量的文章很多。 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. 通常,这仍然会导致设计混乱,因为您将开始在各处传递state参数作为参数。 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. 如果math模块没有提供pi ,那么我不会在您的模块顶部定义它,而不是将其作为参数传递给需要它的任何函数,这不会让您感到困扰。 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. 正如@ prpl.mnky.dshwshr所建议的那样,建议将变量作为参数传递给使用它们的函数。 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 : 可能暗示f1f2f3应该在封装foobarbaz值的类中:

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):
            ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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