Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/343.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_Python 3.x_Global - Fatal编程技术网

Python 为什么访问外部作用域中定义的变量需要全局关键字?

Python 为什么访问外部作用域中定义的变量需要全局关键字?,python,python-3.x,global,Python,Python 3.x,Global,另一个问题没有解释为什么在示例(2)中不使用“global”就不能更改变量time\u verf,但仍然可以对示例(4)中的列表进行更改 我发现我无法从函数中更改全局变量,这些示例清楚地说明了这一点: from datetime import datetime, timedelta time_verf = datetime.now() 我想我理解为什么以下方法有效(1): def check_global(): 全球时间 清洁清单=时间+时间增量(小时数=12) 如果清除列表>检查_globa

另一个问题没有解释为什么在示例(2)中不使用“global”就不能更改变量time\u verf,但仍然可以对示例(4)中的列表进行更改

我发现我无法从函数中更改全局变量,这些示例清楚地说明了这一点:

from datetime import datetime, timedelta
time_verf = datetime.now()
我想我理解为什么以下方法有效(1):

def check_global():
全球时间
清洁清单=时间+时间增量(小时数=12)
如果清除列表>检查_global()
>检查_global()
>检查_global()
>检查全局列表()
>>名单

当您注释掉第2行中的
global time\u verf
语句时

1: def check_global():
2: # global time_verf
3: clean_list = time_verf + timedelta(hours=12)  # время очистки листа
4: if clean_list < datetime.now():
5:     list_verf.clear()
6:     time_verf = datetime.now()
1:def check_global():
2:#全球时间#
3:清洁列表=时间+时间增量(小时=12)#
4:如果clean_list
第6行为局部变量
time\u verf
赋值。它是局部的,因为分配它会将其创建为局部变量。第3行出现错误,因为它引用了代码在第6行中创建的局部变量。如果您没有该分配,则默认情况下,
time\u verf
将是全局的

但变量是否为全局变量并不取决于执行顺序。您似乎期望,因为第3行本身在默认情况下会使
time\u verf
全局,所以它会变为全局,并在第6行中保持全局。但这不是局部变量的工作方式。第6行的出现改变了第3行的含义(和正确性)。解释器检查函数的整个范围,并为代码赋值给的任何名称创建局部变量。因此,由于第6行的原因,
time\u verf
是局部的,即使第3行本身会使其成为全局的


这种行为有很好的理由。假设第3行包含在
if
测试中。然后,根据您似乎期望的行为,如果
if
-test为true,则变量将是全局变量,如果
if
-test为false,则变量将是局部变量

编辑:我同意Roel Schroeven的观点,这里的核心问题是分配

然而,BoarGules给出了关于可变寿命imho的一个很好的答案。此外,我认为这里需要注意的一个重要点是可变性与不变性。这特别涉及问题的第(4)项。而下面的方法很好

a=2.72#全局范围,在函数之前定义
def modify():
b=a+3.14#不向a转让(但在本例中为b转让)
return b#b的作用域是本地的->需要“return”才能使其在外部作用域中可用
在[106]:modify()中
Out[106]:5.86
这失败了:

a=2.72
def modify():#分配!
a+=3.14#在此之前,您需要“全局a”才能使其正常工作
归还
在[108]中:修改()
UnboundLocalError:赋值前引用的局部变量“a”
虽然可以在
modify()
内部调用
a
,但它不能被修改,因为它是类型
float
,因此是一个不可变的对象

另一方面,如果对可变对象(如
列表
)执行相同操作,则

a=[2.72]
def modify():
a[0]=3.14#将引用更改为另一个值。。。
#不需要退货
在[110]:modify()中
在[110]中:a
Out[110]:[3.14]
它不会失败,也不会改变
a
,甚至在功能范围之外!如果调用函数中以前未定义的变量,它将再次失败。请注意,
a[0]=3.14
不是将
a
赋值给某个值,而是将存储在
a
中的引用更改为另一个值。如果在脚本中有多个函数并传递信息,这一点非常重要。
为了进一步阅读,有很多关于这个主题的好资源,例如,作为初学者,也可能在文档中的上。

您找到的资源声明“如果我们需要为全局变量分配新值,那么我们可以通过将变量声明为全局变量来实现”。关键字为“分配”。您可以访问全局变量,对它们调用方法,对它们进行变异,而无需将它们声明为全局变量


当您需要分配给它们时,您需要将它们声明为全局的。

我在这里看到了答案,所以。。。现在找不到问题。。。其思想是,通过将代码中名为“time_verf”下面的赋值行添加到局部变量中(甚至在执行第一行代码之前),我将搜索包含详细信息的帖子。注释掉该行的函数的可能副本只调用变量,而不尝试修改。我认为这是关于可变性与不可变性(列表是可变的,这就是为什么您的底部示例可以工作(也可以使用dict))@VladimirKolenov我的意思是允许您在函数中修改可变对象,例如
列表
,而不声明它是
全局
变量。这是你在(4)中展示的。另一方面,一个不可修改的对象,比如
datetime
,你必须声明为
global
,才能在函数中修改它(或者作为参数/关键字传递),请参见你的示例(1)-(3)。@VladimirKolenov,是的,我认为BoarGules对此给出了很好的解释。它是关于定义变量的时间顺序(代码从上到下)。我添加了一些关于可变性的词语,因为这可能会在脚本中引起一些混乱。IMO可变性与不可变性不是问题的核心。主要的一点是赋值需要全局变量,这对于可变变量和不可变变量都是如此<代码>a=a+[3.14]
需要
全局
偶数fo
def check_global():
    # global time_verf
    clean_list = time_verf + timedelta(hours=12)  # время очистки листа
    if clean_list < datetime.now():
        list_verf.clear()
        time_verf = datetime.now()
    print('ok')

>> check_global()
<< Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<input>", line 3, in check_global
UnboundLocalError: local variable 'time_verf' referenced before assignment
def check_global():
    # global time_verf
    clean_list = time_verf + timedelta(hours=12)  # время очистки листа
    if clean_list < datetime.now():
        list_verf.clear()
        # time_verf = datetime.now()
    print('ok')

>> check_global()
<< ok
list = []

def check_global_list():
    list.append('check')
>> check_global_list()
>> list
<< ['check']
1: def check_global():
2: # global time_verf
3: clean_list = time_verf + timedelta(hours=12)  # время очистки листа
4: if clean_list < datetime.now():
5:     list_verf.clear()
6:     time_verf = datetime.now()