Python 变量作用域
变量作用域(scope)在Python中是一个容易掉坑的地方。
Python的作用域一共有4中,分别是:
- L (Local) 局部作用域
- E (Enclosing) 闭包函数外的函数中
- G (Global) 全局作用域
- B (Built-in) 内建作用域
以 L --> E --> G -->B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。
Python除了def/class/lambda
外,其他如: if/elif/else/ try/except for/while
并不能改变其作用域。定义在他们之内的变量,外部还是可以访问。
>>> if True:
... a = 'I am A' ... >>> a 'I am A' # 定义在if语言中的变量a,外部还是可以访问的。 # 但是需要注意如果if被 def/class/lambda 包裹,在内部赋值,就变成了此 函数/类/lambda 的局部作用域。
在 def/class/lambda
内进行赋值,就变成了其局部的作用域,局部作用域会覆盖全局作用域,但不会影响全局作用域。
g = 1 #全局的
def fun(): g = 2 #局部的 return g print fun() # 结果为2 print g # 结果为1
<br />
但是要注意,有时候想在函数内部引用全局的变量,疏忽了就会出现错误,比如:
#file1.py
var = 1
def fun(): print var var = 200 print fun() #file2.py var = 1 def fun(): var = var + 1 return var print fun() # 这两个函数都会报错UnboundLocalError: local variable 'var' referenced before assignment
在未被赋值之前引用的错误!为什么?因为在函数的内部,解释器探测到var被重新赋值了,所以var成为了局部变量,但是在没有被赋值之前就想使用var,便会出现这个错误。解决的方法是在函数内部添加 globals var
但运行函数后全局的var也会被修改。
<br />
闭包Closure
闭包的定义:如果在一个内部函数里,对在外部函数内(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)
函数嵌套/闭包中的作用域:
a = 1
def external(): global a a = 200 print a b = 100 def internal(): # nonlocal b print b b = 200 return b internal() print b print external()
一样会报错- 引用在赋值之前,Python3有个关键字nonlocal
可以解决这个问题,但在Python2中还是不要尝试修改闭包中的变量。
关于闭包中还有一个坑:
from functools import wrapsdef wrapper(log): def external(F): @wraps(F) def internal(**kw): if False: log = 'modified' print log return internal return external @wrapper('first') def abc(): pass print abc()
也会出现 引用在赋值之前 的错误,原因是解释器探测到了 if False
中的重新赋值,所以不会去闭包的外部函数(Enclosing)中找变量,但 if Flase
不成立没有执行,所以便会出现此错误。除非你还需要else: log='var'
或者 if True
但这样添加逻辑语句就没了意义,所以尽量不要修改闭包中的变量。
好像用常规的方法无法让闭包实现计数器的功能,因为在内部进行 count +=1
便会出现 引用在赋值之前 的错误,解决办法:(或Py3环境下的 nonlocal
关键字)
def counter(start): count =[start] def internal(): count[0] += 1 return count[0] return internal count = counter(0) for n in range(10): print count() # 1,2,3,4,5,6,7,8,9,10 count = counter(0) print count() # 1
由于 list
具有可变性,而字符串是不可变类型。
<br />
locals() 和 globals()
globals()
global
和 globals()
是不同的,global
是关键字用来声明一个局部变量为全局变量。**globals()
和 locals()
**提供了基于字典的访问全局和局部变量的方式
比如:如果函数1内需要定义一个局部变量,名字另一个函数2相同,但又要在函数1内引用这个函数2。
def var(): pass def f2(): var = 'Just a String' f1 = globals()['var'] print var return type(f1) print f2() # Just a String # <type 'function'>
locals()
如果你使用过Python的Web框架,那么你一定经历过需要把一个视图函数内很多的局部变量传递给模板引擎,然后作用在HTML上。虽然你可以有一些更聪明的做法,还你是仍想一次传递很多变量。先不用了解这些语法是怎么来的,用做什么,只需要大致了解locals()是什么。
可以看到,locals()把局部变量都给打包一起扔去了。
@app.route('/')
def view(): user = User.query.all() article = Article.query.all() ip = request.environ.get('HTTP_X_REAL_IP', request.remote_addr) s = 'Just a String' return render_template('index.html', user=user, article = article, ip=ip, s=s) #或者 return render_template('index.html', **locals())
链接:https://www.jianshu.com/p/3bb277c2935c
转载于:https://www.cnblogs.com/lyy-blog/p/9797198.html
Python 变量作用域相关推荐
- Python变量作用域问题
本文最后更新于2018-6-20,可能会因为没有更新而失效.如已失效或需要修正,请联系我! 今天在用Python写程序时突然想起了Python变量作用域的问题,代码如下: def run():glob ...
- [python]变量作用域问题
先列出参考链接: python变量作用域–作者:lovingprince python开发杂货铺:作用域的痛点-作者:Assassin python中在哪些情况下必须使用global来声明全局变量 p ...
- Python 变量作用域问题 函数名.变量名
刚接触Python,主要想利用它做数据处理.我用的是Python2.7.5,win7系统 最近在看<机器学习实战>,第三章决策树中有一段代码,摘抄如下,对于用颜色标注部分,刚开始没看懂什么 ...
- Python 变量作用域与函数(4)
Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Py ...
- Python变量作用域(全局变量和局部变量)
Python变量作用域(全局变量和局部变量) 所谓作用域(Scope),就是变量的有效范围,就是变量可以在哪个范围以内使用.有些变量可以在整段代码的任意位置使用,有些变量只能在函数内部使用,有些变量只 ...
- Python变量作用域的规则以及如何搜索内置作用域
喜欢编程,热爱分享,希望能结交更多志同道合的朋友,一起在学习Python的道路上走得更远!有不懂的问题可以私聊我哦! **作用域:**是指变量的生效范围,例如本地变量.全局变量描述的就是不同的生效范围 ...
- 详解Python变量作用域
本文暂时不讨论类定义中的变量(成员)作用域,改天可能会单独成文介绍. 变量作用域总起来说可以这么理解:1)在函数内如果只引用某个变量的值而没有为其赋新值,该变量为(隐式的)全局变量:2)如果在函数内某 ...
- Python 变量作用域和列表
变量作用域 变量由作用范围限制 分类:按照作用域分类 全局(global):在函数外部定义 局部(local):在函数内部定义 变量的作用范围: 全局变量:在整个全局范围有效 全局碧昂量在局部可以使用 ...
- 【python教程入门学习】Python变量作用域(通俗易懂)
Python 中变量的访问权限取决于其赋值的位置,这个位置被称为变量的作用域.Python 的作用域共有四种,分别是:局部作用域(Local,简写为 L).作用于闭包函数外的函数中的作用域(Enclo ...
最新文章
- 用PHP实现丢手帕问题(约瑟夫问题)
- Java 对象引用以及对象赋值
- [Project Euler] 来做欧拉项目练习题吧: 题目004
- 测试电视是不是4k的软件,怎么判断4K电视真假?教你快速检测的方法!
- python爬虫面试遇到的问题
- viewpager默认界面_使用默认方法的界面演变–第一部分:方法
- java mongo subtract_春数据MongoDB的聚合框架,例外
- ZFS 常见问题解答 及 ZFS Boot 问题探讨
- 将tensor转array
- HDU-1102-Constructing Roads(并查集)
- Kubernetes中使用CronJob定时备份etcd集群数据
- Linked List Sorting (链表)
- 发票专用驱动sjz_增值税发票选择确认平台使用手册
- 记一次代码重构--状态机编程
- 简述前端MVVM框架
- 四分位数(定义、位置、数值)
- 名词用作动词举例_名词活用作动词
- 支付宝小程序H5域名配置
- 软件设计模式--软件设计演变过程
- 用友优普孙永军:制造业的三座“大山”
热门文章
- linux lnmp1.5 部署laravel项目
- 对vuex的一点理解
- git——^和~的区别(转)
- c++性能之对象与指针性能比较、以及java与c++性能对比实测
- 使用无限生命期Session的方法
- linux飞信机器人的安装fetion
- 一个简单的拖动层(兼容IE,FF)
- ASP.NET基础教程-以查询字符串的方式在两个页面之间传递信息
- RAC IP 地址修改
- Extjs4中up()和down()的用法以及组件查找_ComponentQuery类