Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 什么是;“全局变量是坏的”;什么意思?_Python_Global Variables - Fatal编程技术网

Python 什么是;“全局变量是坏的”;什么意思?

Python 什么是;“全局变量是坏的”;什么意思?,python,global-variables,Python,Global Variables,所以我可以读取全局变量 def f() : print x 我也可以分配它 def g() global x x = 3 当人们说“全局变量不好”时,是指读取和赋值都不好,还是仅仅赋值就不好?(我的印象是阅读并不危险)全局变量几乎可以在任何地方更改和访问。这可能包括名称空间和赋值的冲突,而您不希望它们发生冲突 举个例子: def someFunction(): global myVar myVar = "fuuu" print myVar myVa

所以我可以读取全局变量

def f() :
  print x
我也可以分配它

def g()
  global x
  x = 3

当人们说“全局变量不好”时,是指读取和赋值都不好,还是仅仅赋值就不好?(我的印象是阅读并不危险)

全局变量几乎可以在任何地方更改和访问。这可能包括名称空间和赋值的冲突,而您不希望它们发生冲突

举个例子:

def someFunction(): 
    global myVar 
    myVar = "fuuu" 
    print myVar

myVar = "baa" 
f() 
print myVar 
将以类似的方式结束

fuuu
fuuu 
而你可能会想到

fuuu 
baa

所以我想说这两种变体都不太危险。

问题与其说是“全局==坏”,不如说是“全局可变状态使程序流难以推理”

要进行说明,请想象此函数:

def frob():
    if my_global:
        wibble()
    else:
        wobble()
也就是说,
frob()
的行为取决于状态,无论是从
frob()
的主体还是从任何可能调用它的代码来看,谁的本质都不明显。您必须尝试找出哪些更改
my_global
,以及与调用
frob()
相关的更改发生的时间


在编写小脚本时,这不是什么大问题,您可以看到并理解全局变量更改的所有位置,并且可能在全局变量更改时以及调用依赖位时在您的头脑中进行排序。在大型程序中,这需要付出更多的努力,以至于全局可变状态被广泛认为是一种反模式。

在所有编程语言中,我们有一个称为范围的概念。简单地说,变量的范围是源代码中可以访问该变量的区域

想象一下我们没有这个。你有没有尝试过在一个网站或游戏上注册一个需要唯一用户名的帐户?在找到一个有效的方法之前,你有没有检查过三四个?你是否最终得到了与你最初想要的东西不一样的东西,而在它的末尾附加了无用的信息(
username\u 2014\u 1234

现在假设没有编程语言具有作用域。每次必须命名一个变量时,您都会经历这个过程!即使在您自己的程序中,您也无法执行以下操作:

x = 5;
function add_6_to_x(x) {
    return x + 6;
}
using System.IO;
println("The quick brown fox jumped over the lazy dog.");
在适当的范围内(给函数中的变量赋予它们自己的局部范围),这是可行的,因为
x
在这两个地方引用不同的东西。如果没有它,就会出现名称冲突,这必须由编译器来解决,或者更可能的是,由可怜的程序员来解决,因为他们不能简单地命名一个变量,过自己的生活

一些编程语言已经超出了简单的范围,引入了名称空间。名称空间可以采用两种方式之一(甚至两种方式都可以!)。他们允许的一件事是限定的命名方案。限定名称通过给名称一个前缀来表示名称的来源,从而解决名称冲突。假设有一种编程语言(没有)有两个
println
函数。第一个是在
System.IO
中,您可以像预期的那样打印到终端(stdout)或文件。另一个在
System.Printers
中,尝试连接到系统的默认打印机,并在纸上实际打印该行。所以如果我写:

println("The quick brown fox jumped over the lazy dog.");
我是什么意思?它应该打印到屏幕上还是打印到纸上?但是使用名称空间:

using System;
System.IO.println("The quick brown fox jumped over the lazy dog.");
现在完全清楚了。等等,你可能会说:这到底给我带来了什么?毕竟,我得多打字。这里的好处是我们可以有两个完全不同的功能,由两个同名的独立软件包提供。想一想:你能想象一下,如果每次你为一种特定的语言编写代码时,你都必须浏览网页,看看以前是否有人定义过这个函数名吗?糟透了

名称空间所做的另一件事是允许灵活性。如果我不想编写
System.IO.println
,该怎么办?只要我只使用一个就可以了。大多数语言都是这样解决的:

x = 5;
function add_6_to_x(x) {
    return x + 6;
}
using System.IO;
println("The quick brown fox jumped over the lazy dog.");
我只需在文件的顶部添加一个名称空间限定,就可以整天无条件地调用
println
。基本上,它将
System.IO
名称空间与我的文件[1]的名称空间合并

两者都用怎么样?大多数语言都可以:

using System.IO.println;
using System.Printers.println as print_out;
现在,它们有了自己的独立(简短的、用户定义的)名称。太好了

显然,这给了开发人员很大的能力和灵活性,并且解决了世界各地的开发人员能够,而且很可能会,为事物取相同的名称的问题,即使它们在上下文上完全不同。事实上,作用域或名称空间就是这样:标识符有效的上下文,以及它们所指的内容

任何不在这种背景下的东西都是全球性的。有时全局变量看起来很有用,因为它们在普通变量无法使用的地方可用。对于新程序员来说,这通常很诱人,因为如果不知道如何访问变量,只需将其设置为全局变量,就可以访问该变量

但是全局名称由于忽略了作用域和名称空间的常规规则(因为全局意味着它们存在于每个作用域和名称空间中),违反了上述所有安排。如果每个人都简单地将他们所有的变量设置为全局变量,我们就会回到可怕的
myVar_2014_1234
世界,可能很多事情都会停止工作

所以,当人们说“全球名字不好”,或者因为你使用了一个名字而表现得像你刚刚复活了希特勒,那是因为它们没有用处。这是因为他们喜欢我们整洁地包含作用域和名称空间的美好世界(毕竟,它们存在于每种现代编程语言中都是有原因的!),而您违反了这一协议。这和人们不喜欢你扔垃圾的原因是一样的