简体   繁体   English

用于创建和更改全局变量的 Python 语法

[英]Python syntax for creating and changing global variables

Very basic Python question but I want to make sure I'm using the global keyword properly after a couple of false starts.非常基本的 Python 问题,但我想确保在几次错误启动后我正确使用了global关键字。

  1. Creating a variable that needs to be global inside a function:在函数内部创建一个需要全局的变量:
def my_function():
    global x # creates a global variable
    x = 1
    
my_function()
  1. Changing the value of a global variable that already exists outside of the function that is changing it:更改已存在于正在更改它的函数之外的全局变量的值:
x = 1 # creates a global variable

def my_function():
    global x
    x = 2
    
my_function()

That right?对吗?

Seems like a lot of people aren't big fans of global so if there is a better way to handle reading from and writing to multiple global variables from within different functions I'd love to hear it.似乎很多人都不是global的忠实粉丝,所以如果有更好的方法来处理从不同函数中读取和写入多个全局变量,我很想听听。 Thanks!谢谢!

I think you got things the wrong way around: it's not that people aren't big fans of the global keyword and want you to use a different way to re-assign global variables.我认为你把事情弄错了:这并不是说人们不是global关键字的忠实粉丝,而是希望你使用不同的方式来重新分配全局变量。 It's that mutable global state is a code smell in itself.可变的全局状态本身就是一种代码味道。

A "code smell" refers to how expert programmers consider certain code practices to "smell". “代码气味”是指专业程序员如何将某些代码实践视为“气味”。 Much like real world smells, they are not necessarily bad in and of themselves, but they point to possible problems: a real world smell might tell you that food has gone bad or there might be a gas leak.就像现实世界的气味一样,它们本身不一定不好,但它们指出了可能存在的问题:现实世界的气味可能会告诉您食物变质或可能有煤气泄漏。 A code smell might tell you the code is going to become an unmaintainable mess if you're not careful, or that the probability of there being bugs you're not seeing is higher than normal.代码味道可能会告诉您,如果您不小心,代码将变得无法维护,或者存在您看不到的错误的可能性高于正常情况。

Mutating global variables means that if you have two functions foo() and bar() , then calling them in a specific order may break things.改变全局变量意味着如果你有两个函数foo()bar() ,那么以特定顺序调用它们可能会破坏事情。 Example:例子:

X = 0
DATA = 'ok'

def foo():
    global DATA
    if X == 0:
        DATA = 'bad'

def bar():
    global X
    if DATA == 'ok':
        X = 1

Even worse, it may be the case that it depends on whether or not you call spam() in a completely different part of your program, For a couple of functions and global variables, this is usually something you can mentally keep track of, but as your program grows.更糟糕的是,这可能取决于您是否在程序的完全不同部分调用spam() ,对于几个函数和全局变量,这通常是您可以在脑海中跟踪的东西,但是随着你的程序的增长。 the opportunities for weird 5D quantum bugs increases exponentially.奇怪的 5D 量子错误的机会呈指数增长。

The solution is to make data dependencies explicit.解决方案是使数据依赖显式化。

We can do that by, among other things, passing values as arguments and returning values from functions, rather than relying on global variables.我们可以通过将值作为参数传递并从函数返回值来做到这一点,而不是依赖于全局变量。

In your example, my_function() could return 2 .在您的示例中, my_function()可以返回2 In my example, instead foo() and bar() both depending and modifying a global variable, they could take a value and return another one.在我的示例中, foo()bar()都依赖并修改全局变量,它们可以取一个值并返回另一个值。 For example:例如:

def foo(x: int) -> str:
    if x == 0:
        return 'bad'
    return 'ok'

def bar(data: str) -> int:
    if data == 'ok':
        return 1
    return 0

Now it's very clear that ordering is important when you call foo() or bar() !现在很明显,当您调用foo()bar()时,顺序很重要!

The difference between和...之间的不同

foo()
bar()

and

bar()
foo()

... depends on you knowing how foo and bar are implemented. ...取决于您了解foobar的实现方式。

That

data = foo()
bar(data)

and

x = bar()
foo(x)

don't mean the same thing is obvious from the code itself.并不意味着从代码本身可以看出同样的事情。

Even better, if you know foo and bar don't depend on mutable global state, you know that the result can't depend on a call to spam() that may or may not happen in a completely different module.更好的是,如果您知道foobar不依赖于可变的全局状态,您就会知道结果不能依赖于对spam()的调用,这可能发生在完全不同的模块中,也可能不发生。

You are mostly correct.你基本上是对的。 However, the global keyword does not create a variable.但是, global关键字不会创建变量。 It simply marks the name as belonging to the global scope, rather than the local scope.它只是将名称标记为属于全局范围,而不是本地范围。 For example, the following例如,以下

def foo():
    global x

foo()

does not create a global variable named x , because there is never an assignment to the name x .不会创建名为x的全局变量,因为从来没有对名称x赋值 Your first example, more precisely commented, would look like你的第一个例子,更准确地评论,看起来像

def my_function():
    global x
    x = 1   # creates a global variable if it doesn't already exist
    
my_function()

Global variables are frowned upon because it makes it harder to know who might change a variable, and when or where that change might occur.全局变量是不受欢迎的,因为它使得更难知道谁可能会更改变量,以及更改可能发生的时间和地点。 The alternative is for my_function to receive an argument and/or return a value, and let the caller decide what argument to provide and what to do with the return value.另一种方法是让my_function接收一个参数和/或返回一个值,让调用者决定提供什么参数以及如何处理返回值。 For example,例如,

x = 1  # Global variable

def my_function(y):
    return y + 1

x = my_function(x)
assert x == 2

This is not to say you will never use global variables, but you should consider whether it makes sense to use a global instead of passing arguments to and receiving values from a function instead.这并不是说您永远不会使用全局变量,但您应该考虑使用全局变量而不是将参数传递给函数并从函数接收值是否有意义。

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

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