python作用域 scope
可以先看:http://www.cnblogs.com/youxin/p/3645734.html
几个概念:
python能够改变变量作用域的代码段是def、class、lamda.
if/elif/else、try/except/finally、for/while 并不能涉及变量作用域的更改,也就是说他们的代码块中的变量,在外部也是可以访问的
变量搜索路径是:本地变量->全局变量
作用域搜索规则:
LEGB Rule.
L. Local. (Names assigned in any way within a function (def
or lambda
)), and not declared global in that function.
E. Enclosing function locals. (Name in the local scope of any and all enclosing functions (def
or lambda
), form inner to outer.
“封闭式”的作用域规则适应于函数定义函数时,也就是说,在函数体内定义了一个新的函数。这个函数体内的函数是外函数的局部命名空间中的一部分,意味着只有在外函数执行期间才能够运行
G. Global (module). Names assigned at the top-level of a module file, or declared global in a def
within the file.
B. Built-in (Python). Names preassigned in the built-in names module : open
,range
,SyntaxError
,
下面一个程序,运行时为什么报错:
def func1(param=None):
def func2():
if not param:
param = 'default'
print param
# Just return func2.
return func2
if __name__ == '__main__':
func1('test')()
Traceback (most recent call last):
File "test.py", line 11, in
func1('test')()
File "test.py", line 3, in func2
if not param:
UnboundLocalError: local variable 'param' referenced before assignment
为什么?param是func1的。
先看下面的类似例子:
def foo():
m=3
def bar(): a=4
return a+m
return bar
foo()()
运行正常,可是如果加上一句:
if not m:
m=1
立刻报类似错误:UnboundLocalError: local variable 'm' referenced before assignment。
错误的原因是python闭包原理;
def foo():
m=3
n=5
def bar():
a=4
return m+n+a
return bar >>>bar = foo()
>>>bar()
12
cell对象的引入,是为了实现被多个作用域引用的变量。
对每一个这样的变量,都用一个cell对象来保存 其值 。 拿之前的示例来说,m和n既在foo函数的作用域中被引用,又在bar
函数的作用域中被引用,所以m, n引用的值,都会在一个cell对象中。
这两个int型的cell分别存储了m和n的值。
无论是在外部函数中定义,还是在内部函数中调用,引用的指向都是cell对象中的值。
内部函数无法修改cell对象中的值,如果尝试修改m的值,编译器会认为m是函数
bar的局部变量,同时foo代码块中的m也会被认为是函数foo的局部变量,两个m分别在各自的作用域下起作用。
所以我们看到了:
if not param:
param=5
尝试给param赋值,param就成了局部变量,那么之前的if not param就报错,因为param还没有赋值。还是不清楚为什么?参考:http://www.cnblogs.com/btchenguang/archive/2012/08/29/2662571.html
隔几天有发现了答案:
http://www.cnblogs.com/youxin/p/3383059.html
def logging_decorator(func):
def wrapper():
wrapper.count += 1
print "The function I modify has been called {0} time(s)".format(wrapper.count)
func()
wrapper.count = 0
return wrapper def a_function():
print "I'm a normal function."
你也许正疑惑为什么我们的计数器是wrapper
的一个属性而不是一个普通的变量。难道wrapper
的闭包环境不是让我们访问在其局部作用域中声明的任意变量么?是的,但有个问题。
但有个问题。Python中,闭包允许对其函数作用域链中任一变量的进行任意读操作,但只允许对可变对象(列表、字典、等等)进行写操作。整数在Python中是非可变对象,因此我们不能修改 wrapper
内部整型变量的值。相反,我们将计数器作为 wrapper
的一个属性—一个可变对象,因此可以随我们自己增大它的值。。
def func1():
param=[1,2]
def func2(): if not param:
param.append(5) print param
#just return func2
return func2 func1()();
程序运行正常。
如果改成:
if not param:
param=[3,4]
还是报同样的错。
所以,闭包对外部的可变变量不能使用=赋值,可以修改。
If you’re curious, you can read about the principles of LEGB. You have to understand a bit about compilers and the AST to get what’s going on behind the scenes. You might think that replacing lines 3-4 with:
param = param or 'default'
Might work. But no. You can’t assign the same parameter at the local level if the enclosing level defines it. Even this fails:
param = param
What to do?
There are a few ways to get around this.
- Assign
param
outside of func2. This doesn’t work if you need the default value to be dependent on what params func2 receives. - Use a second variable,
param2
inside of func2 (posted below).
Here is the solution suggested by our commenter Avazu:
def func1(param=None):
def func2(param2=param):
if not param2:
param2 = 'default'
print param2
# Just return func2.
return func2
上面例子参考:http://blog.mozilla.org/webdev/2011/01/31/python-scoping-understanding-legb/
python作用域 scope的更多相关文章
- python作用域和多继承
python作用域 python无块级作用域 看c语言代码: #include<stdio.h> int main() { > ) { ; } printf("i = %d ...
- 聊一下JS中的作用域scope和闭包closure
聊一下JS中的作用域scope和闭包closure scope和closure是javascript中两个非常关键的概念,前者JS用多了还比较好理解,closure就不一样了.我就被这个概念困扰了很久 ...
- 理解AngularJS的作用域Scope
AngularJS中,子作用域一般都会通过JavaScript原型继承机制继承其父作用域的属性和方法.但有一个例外:在directive中使用scope: { ... },这种方式创建的作用域是一个独 ...
- 理解angularJS中作用域$scope
angularJS中作用域是什么 作用域(scope)是构成angularJS应用的核心基础,在整个框架中都被广泛使用,因此了解它如何工作是非常重要的 应用的作用域是和应用的数据模型相关联的,同时作用 ...
- python 作用域(LEGB)
def fa(a): b = 200 c = 888 def fb(b): print(b) print(a) print(c) print(sum) return fb c = 2 sum = 10 ...
- Python作用域详述
作用域是指变量的生效范围,例如本地变量.全局变量描述的就是不同的生效范围. python的变量作用域的规则非常简单,可以说是所有语言中最直观.最容易理解的作用域. 在开始介绍作用域之前,先抛一个问题: ...
- Python3基础-Python作用域详述(转载)
转载文章 转载文章 作者:骏马金龙 出处:http://www.cnblogs.com/f-ck-need-u/p/9925021.html Python作用域详述 作用域是指变量的生效范围,例如本地 ...
- angualar入门学习-- 作用域$scope
作用域$scope: 是ng执行环境,视图与controller之间的胶水,双向绑定的基础 $scope提供里$watch方法,监听数据模型变化 $scope提供里$apply方法,将数据模型变化更新 ...
- Python之路Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数
Python之路Python作用域.匿名函数.函数式编程.map函数.filter函数.reduce函数 一.作用域 return 可以返回任意值例子 def test1(): print(" ...
随机推荐
- java反射的应用+mybatis+spring动态生成数据库表
最近接触了一个类似于代码生成工具的活.思路是,通过java的反射机制得到类的字段和字段类型, 从而可以创建一个map集合存储表名(由类名决定的特殊结构字符串),表字段(由类变量确定),表字段类型(由变 ...
- [上传下载] C# ImageUpload图片上传类教程与源码下载 (转载)
点击下载 ImageUpload.zip 功能如下图片1.设置属性后上传图片,用法如下 /// <summary> /// 图片上传类 /// </summary> //--- ...
- 最新的C#SqlHelper 类苏飞修改版(转载)
/// <summary> /// 类说明:公共的数据库访问访问类 /// 编码日期:2010-4-22 /// 编 码 人:苏飞 /// 联系方式:361983679 Email:[ur ...
- jquery”ScriptResourceMapping
要“jquery”ScriptResourceMapping.请添加一个名为 jquery (区分大小写)的 ScriptResourceMapping.”的解决办法. 1.先将aspnet.scri ...
- LINQ 101——约束、投影、排序
什么是LINQ:LINQ 是一组 .NET Framework 扩展模块集合,内含语言集成查询.集合以及转换操作.它使用查询的本机语言语法来扩展 C# 和 Visual Basic,并提供利用这些功能 ...
- Graphics类绘制图形
1. 画直线 void drawLine(int startX,int startY,int endX,int endY); 四个参数分别为:起始点的x坐标和y坐标以及终点的x坐标和y坐标,该方法用于 ...
- (传智博客)tp开发第一天之tp执行流程分析笔记
1.入口文件index.php 2.ThinkPHP/ThinkPHP.php require THINK_PATH.'Common/runtime.php'; 3.ThinkPHP/Common/r ...
- MVVM模式应用 之的RelayCommand的使用
实现MVVM模式Command是立下了汗马功劳.当然ICommand要引用using System.Windows.Input命名空间. 比如: (1)我们在xaml页面有一个Button按钮,我们需 ...
- struts-json
Struts2序列化的属性,该属性在action中必须有对应的getter方法 如果action的属性很多,我们想要从Action返回到调用页面的数据.这个时候配置includeProperties或 ...
- 《paste命令》-linux命令五分钟系列之二十
本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket. 为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. ...