Python-作用域

Posted dongliping

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python-作用域相关的知识,希望对你有一定的参考价值。

一个标识符的可见范围,就是标识符的作用域。一般常说的是变量的作用域。

先看一段代码

# -*- coding:utf-8 -*-
x=5
def foo():
    print(x)
foo()

  

1 x=5
2 def foo():
3     x+=1
4     print(x)
5 foo()

问:x到底可见不可见?

 

这里就引入2个概念

全局作用域 --global

在整个程序运行环境中可见。

局部作用域-- local

在函数,类等内部可见。局部变量使用范围不能超过其所在的局部作用域。

 

回到上面的函数

第一段代码中x=5定义在函数外部,相当全局作用域,在整个程序运行环境中可见。所以第1段程序是没有问题的。

第2段代码会报本地变量未赋值被引用。Why?赋值即定义,x+=1相当于在函数内重新定义了1个局部变量x,那么foo内部所有X都是这个局部变量X,但是X没完成赋值就被右边拿来做加1操作了(赋值语句先执行等号右边的)。

 

嵌套函数

eg1

 1 # -*- coding:utf-8 -*-
 2 def outer1():
 3     o=65
 4     def inner():
 5         print("inner {}".format(o))
 6         print(chr(o))
 7     print("outer {}".format(o))
 8     inner()
 9 
10 outer1()

输出结果:

outer 65
inner 65
A

 

eg2

 1 # -*- coding:utf-8 -*-
 2 def outer2():
 3     o=65
 4     def inner():
 5         o=67
 6         print("inner {}".format(o))
 7         print(chr(o))
 8     print("outer {}".format(o))
 9     inner()
10 
11 outer2()

输出结果:

outer 65
inner 67
C

从嵌套结构例子可以看出:

外层变量作用域在内层作用域可见;

内层作用域inner中,如果定义了o=67,相当于当前作用域重新定义了一个新的变量o,但是这个o并没有覆盖外层作用域outer中的o。

 

全局变量Global

1 # -*- coding:utf-8 -*-
2 x=5
3 def foo():
4     global x  
5     x+=1

使用global关键字的变量,将foo内的x声明为使用外部的全部作用域中定义X。全局作用域中必须要有X的定义。

 

1 # -*- coding:utf-8 -*-
2 def foo():
3     global x
4     x=20
5     x+=1

使用global关键字的变量,将foo内的x声明为使用外部的全部作用域中定义X。

但是X=20赋值即定义,x在内部作用域为一个外部作用的变量赋值,所有x+=1不会报错。注意,这里的x的作用域还是全局的。

 

Global的使用原则

  • 外部作用域变量在内部作用域可见,但是也不要在这个内部的局部作用域中直接使用(因为函数的目的就是为了封装,尽量与外界隔离);
  • 如果函数需要使用外部全局变量,请使用函数的形参传参解决;
  • 一句话不用global。

闭包

自由变量:未在本地作用域中定于的变量。例如定义在内层函数的外层函数的作用域中的变量。

闭包:就是一个概念,出现在嵌套函数中。指的是内层函数引用到了外层函数的自由变量就形成了闭包。

 1 # -*- coding:utf-8 -*-
 2 def couter():
 3     c=[0]
 4     def inc():
 5         c[0]+=1
 6         return c[0]
 7     return inc
 8 foo=couter()
 9 print(foo(),foo())
10 c=200
11 print(foo())

输出结果:

1 2
3

第5行是对变量的元素的修改,而不是对变量C赋值。

c=200和couter中的c不一样,inc引用的是自由变量couter中的c。

 

以上是关于Python-作用域的主要内容,如果未能解决你的问题,请参考以下文章

JS 作用域及作用域链

JS 作用域及作用域链

作用域是什么?

JavaScript 作用域 与 作用域链

Python名称绑定和作用域的关系??

JS---闭包