Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.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 3.x 在Python中,列表变量和字符串变量的作用域是否不同?_Python 3.x_String_List_Scope - Fatal编程技术网

Python 3.x 在Python中,列表变量和字符串变量的作用域是否不同?

Python 3.x 在Python中,列表变量和字符串变量的作用域是否不同?,python-3.x,string,list,scope,Python 3.x,String,List,Scope,我正在学习Python 3中的作用域,这个例子让我感到困惑。在函数内调用时比较列表变量和字符串变量的行为: foo1 = [] foo2 = '' def f(): foo1.append(3) global foo2 foo2 += 'c' print('foo1-in-f:',foo1) print('foo2-in-f:',foo2) print('foo1-before:',foo1) print('foo2-before:',foo2) f()

我正在学习Python 3中的作用域,这个例子让我感到困惑。在函数内调用时比较列表变量和字符串变量的行为:

foo1 = []
foo2 = ''
def f():
    foo1.append(3)
    global foo2
    foo2 += 'c'
    print('foo1-in-f:',foo1)
    print('foo2-in-f:',foo2)

print('foo1-before:',foo1)
print('foo2-before:',foo2)
f()
print('foo1-after:',foo1)
print('foo2-after:',foo2)
正如预期的那样,输出为:

foo1-before: []
foo2-before:
foo1-in-f: [3]
foo2-in-f: c
foo1-after: [3]
foo2-after: c
我不明白为什么字符串必须是声明的全局的,如
global foo2
行,但列表是未声明的全局的,如没有行
global foo1

我运行代码时忽略了行
global foo2
,毫不奇怪地得到了
UnboundedLocalError:赋值前引用的局部变量'foo2'。但是,为什么我没有得到
foo1
的这个错误呢


任何见解都值得赞赏。我想确保我了解这是如何工作的。

您需要知道变量作用域在Python中是如何工作的。Python不要求您声明变量,但假定在函数体中分配的变量是局部变量。您可以看到编译器在生成的字节码中反映了这一点:

foo1=[]
foo2=''
def():
foo1.追加(3)
foo2+=“c”
从dis导入dis
dis(f)
foo1
是从全局上下文加载的,因为
foo1.append(3)
是项分配操作-它修改实际引用。AFAIK Python字符串是不可变的,这意味着您需要在执行赋值之前复制该值,这是您在函数内部执行的操作,因为
foo2+='c'
将实际创建一个新字符串。尝试运行
foo1+=[3]
,您将得到与
foo1
相同的
UnboundLocalError

foo1.append(3)
是一种项目分配操作,相当于
foo1[len(foo1):]=[3]
。由于上述原因,Python字符串无法执行此类操作-请尝试运行
foo2[:]=“c”
,您将得到错误
“str”对象不支持项分配


现在,global关键字基本上告诉解释器将
foo2
视为一个全局变量,而不管函数中如何赋值。

在Python函数中,所有变量引用都假定为全局变量,除非在本地命名。所有新对象都是在本地作用域中创建的,并且在将对象传输或修改到另一个作用域时有限制

你可以做:

a=1
def f(): return a+1      # unnamed integer object created and returned

>>> f()
2
您可以修改全局可变变量的内容,因为这不会将本地命名的对象分配给全局范围:

ls=['string']
def f():
    ls.append('another')  # unnamed string object created and added to ls
    ls[0]+='_modified'    # ls[0] read, new object created with +=, 
                          # new object added to ls[0]   

>>> f()
>>> ls
['string_modified', 'another']
ls=[]
def f():
    ls+=['new entry'] # UnboundLocalError
但是使用
ls+=[something]
将是一个错误,因为赋值
+=
被视为
ls
在作用域中是局部的,然后被重新分配到全局作用域:

ls=['string']
def f():
    ls.append('another')  # unnamed string object created and added to ls
    ls[0]+='_modified'    # ls[0] read, new object created with +=, 
                          # new object added to ls[0]   

>>> f()
>>> ls
['string_modified', 'another']
ls=[]
def f():
    ls+=['new entry'] # UnboundLocalError
您看到的问题不一定是修改全局变量。将函数在本地使用的名称重新指定给全局作用域

Python网站上有一个


Eli Bendersky的博客上有一个链接。

+=
是作为可变类型的变异实现的,但作为不可变类型的重新绑定。一个要点是
a+=b
通常并不等同于
a=a+b
。(对于字符串,正如您所观察到的那样)。感谢您提供的澄清示例和其他链接。我将深入研究+=运算符。乍一看,我假设
a+=1
等同于
a=a+1
。此外,您在列表中包装字符串的方法非常巧妙。例如,在退出函数后,我可以“连接”完整字符串,如:
“”。join(['Zapdos','used','Thunder.])
谢谢,您对
dis
读数的评论非常有用!我将在将来使用这个软件包,当遇到令人困惑的行为时,我会从引擎盖下面看看。