命名空间

全局变量和局部变量

       全局变量:在函数外定义,在任何一个函数内都可使用。

  只在函数体内(某个范围)起作用的变量称为局部变量。

>>> x = 2    # 全局变量
>>> def func():
...     x = 9    # 局部变量
...     print('这是局部变量x=', x)
...
>>> func()
这是局部变量x= 9
>>> print('这是全局变量x=', x)
这是全局变量x= 2

  局部(函数内)作用域内声明全局变量:

>>> x = 2
>>> def func():
...     global x    # 在函数体内声明全局变量,即声明此处的x是全局变量
...     x = 9    # x是全局变量,修改的也是全局变量的值
...     print('这是局部变量x=', x)
...
>>> func()
这是局部变量x= 9
>>> print('这是全局变量x=', x)
这是全局变量x= 9

  如果函数内部没有global关键字,则函数内部对于全局变量能读取,不能重新赋值;当函数内部用global声明了全局变量后,才能在函数内部整体修改全局变量。

  而当全局变量是可变类型的对象时,在不用global关键字的情况下,依然是不能对可变类型的全局变量重新赋值,或者进行整体修改。但是却能够修改可变类型全局变量的内容,即对其内部进行操作。比如全局变量是个列表,在函数内部没有global的情况下,可以向此全局变量列表中增加或删除或修改列表中的内容。如果想将可变类型的全局变量整体修改了(或重新赋值),则依然要用global声明。

>>> num = [22, 33, 55]    # 可变类型列表作为全局变量
>>> def func():
...     num.append('python')    # 函数内实现对列表全局变量的修改
...
>>> func()
>>> print(num)
[22, 33, 55, 'python']    # 局部内成功的修改了可变类型的全局变量

>>> name = ['zhangsan', 'lisi']
>>> def func():
...     name = ['wang', 'yang']   # 函数内对列表重新赋值,不能改变全局变量,此处为新的同名变量
...     print(name)    # 局部变量name
...
>>> print(name)    # 打印全局变量name
['zhangsan', 'lisi']
>>> func()
['wang', 'yang']    # 局部同名变量name
>>> print(name)    # 全局变量不会被整体修改
['zhangsan', 'lisi']

>>> name = ['zhangsan', 'lisi']
>>> def func():
...     global name    # 加上global声明全局变量
...     name = ['wang', 'yang']    # 整体修改可变类型的全局变量
...     print(name)
...
>>> print(name)    # 打印全局变量
['zhangsan', 'lisi']
>>> func()    # 执行函数,全局变量被整体修改
['wang', 'yang']
>>> print(name)    # 打印修改后的全局变量
['wang', 'yang']

>>> def func():    # 定义删除列表全局变量中的元素的函数
...     del name[0]    # 删除列表全局变量的第一个元素
...
>>> print(name)
['wang', 'yang']
>>> func()
>>> print(name)    # 列表全局变量内部被修改
['yang']

  操作列表全局变量时,运算符+和+=的区别:

>>> num = [100, 'java']
>>> def func(num):    # 定义函数,将列表全局变量num传给函数
...     num += num    # 实现了列表全局变量内部的修改,相当于num.append(num)
...     print(num)    # 打印的是修改后的列表全局变量
...
>>> print(num)    # 打印原列表全局变量
[100, 'java']
>>> func(num)    # 执行函数,函数内列表全局变量内部会被修改
[100, 'java', 100, 'java']
>>> print(num)    # 打印修改后的列表全局变量
[100, 'java', 100, 'java']

>>> num = [100, 'java']
>>> def func(num):    # 定义函数,将列表全局变量num传给函数
...     num = num + num    # 以这种方式,不会修改列表全局变量,而是新创建一个同名局部变量
...     print(num)    # 打印局部变量
...
>>> print(num)    # 打印列表全局变量
 [100, 'java']
>>> func(num)
[100, 'java', 100, 'java']
>>> print(num)    # 列表全局变量没有被修改
[100, 'java']

全局变量要慎用,因为这往往容易引起变量的混乱。

         全局变量全部大写;局部变量全部小写。

         局部变量和全局变量是在不同的范围内起作用,即变量产生作用的区域,简称作用域

 

作用域

         python中的作用域属于静态作用域,即python中的变量作用域由它在程序中的位置决定的。

         python的作用域可划分为四个层级:

                  Local:局部作用域,或称为本地作用域。

                  Enclosing:嵌套作用域。

                  Global:全局作用域。

                  Built-in:内建作用域。

         对于一个变量,python是按照上述从前到后的顺序,在不同的作用域中查找。

         在python中,变量的作用域在函数、类中才能被改变。

 

命名空间(Namespace)

         命名空间的分类:

                  本地命名空间(Function&Class: Local Namespace):模块中有函数或者类,每个函数或者类所定义的命名空间就是本地命名空间。如果函数结束或抛出了异常,则本地命名空间也结束了。

                  全局命名空间(Module: Global Namespace):每个模块创建自己所拥有的全局命名空间,不同模块的全局命名空间彼此相互独立,不会互相干扰。

                  内置命名空间:python运行起来,它们就存在了。内置函数的命名空间都属于内置命名空间,所以我们可以在任何程序中直接运行它们。

         三种命名空间从里到外的顺序是本地命名空间、全局命名空间、内置命名空间。

         访问本地命名空间使用locals(),访问全局命名空间使用globals()。命名空间中的数据存储结构和字典是一样的。

对于不同的命名空间,有不同的查找顺序(从里到外)和不同的生命周期

 

作用域综合:

  在局部中直接使用全局变量:

>>> x = 2    # 全局变量
>>> def func(y):
...     print(x+y)    # 函数中直接使用全局变量
...
>>> func(7)
9

警告:像这样在局部中直接使用全局变量的方式是众多bug的根源,务必慎用全局变量。

局部中定义同名变量,覆盖全局变量:

>>> x = 2    # 全局变量
>>> def func(y):
...     x = 9    # 局部变量
...     print(x+y)
...
>>> func(9)
18
>>> print(x)    # 全局域中,x是全局变量
2

局部中声明全局变量:

>>> x = 2
>>> def func(y):
...     global x    # 函数内声明全局变量
...     x = 9    # 这是全局变量
...     print(x+y)
...
>>> func(9)
18
>>> print(x)
9

  在全局中可使用globals()来访问全局变量,这个函数类似于函数vars()在全局中,返回一个包含全局变量的字典。

>>> globals()     # 返回一个包含全局变量的字典
{'__loader__': <class '_frozen_importlib.BuiltinImporter'>, 'func': <function func at 0x7f34c0a30840>, '__spec__': None, 'name': 'Jack', '__package__': None, '__name__': '__main__', '__doc__': None, 'x': 9, '__builtins__': <module 'builtins' (built-in)>}
>>> globals()['name']    # 从返回的包含全局变量的字典中取出数据
'Jack'
>>> vars()    # 类似于vars()在全局中
{'__loader__': <class '_frozen_importlib.BuiltinImporter'>, 'func': <function func at 0x7f34c0a308c8>, '__spec__': None, 'name': 'Jack', '__package__': None, '__name__': '__main__', '__doc__': None, 'x': 9, '__builtins__': <module 'builtins' (built-in)>}
>>> vars()['name']
'Jack'

  在局部中可使用locals()返回一个局部变量的字典。类似于函数vars()在局部中。

>>> def func():
...     age = 22
...     lang = 'python'
...     print(locals())    # 返回一个包含局部变量的字典
...     print(vars())    # 类似于vars()在局部中
...
>>> func()
{'age': 22, 'lang': 'python'}
{'age': 22, 'lang': 'python'}

 

Help on built-in function vars in module builtins:

 

vars(...)

    vars([object]) -> dictionary

 

    Without arguments, equivalent to locals().

With an argument, equivalent to object.__dict__.

 

posted @ 2018-09-17 16:46  从python开始  阅读(341)  评论(0编辑  收藏  举报