可以先看: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的更多相关文章

  1. python作用域和多继承

    python作用域 python无块级作用域 看c语言代码: #include<stdio.h> int main() { > ) { ; } printf("i = %d ...

  2. 聊一下JS中的作用域scope和闭包closure

    聊一下JS中的作用域scope和闭包closure scope和closure是javascript中两个非常关键的概念,前者JS用多了还比较好理解,closure就不一样了.我就被这个概念困扰了很久 ...

  3. 理解AngularJS的作用域Scope

    AngularJS中,子作用域一般都会通过JavaScript原型继承机制继承其父作用域的属性和方法.但有一个例外:在directive中使用scope: { ... },这种方式创建的作用域是一个独 ...

  4. 理解angularJS中作用域$scope

    angularJS中作用域是什么 作用域(scope)是构成angularJS应用的核心基础,在整个框架中都被广泛使用,因此了解它如何工作是非常重要的 应用的作用域是和应用的数据模型相关联的,同时作用 ...

  5. 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 ...

  6. Python作用域详述

    作用域是指变量的生效范围,例如本地变量.全局变量描述的就是不同的生效范围. python的变量作用域的规则非常简单,可以说是所有语言中最直观.最容易理解的作用域. 在开始介绍作用域之前,先抛一个问题: ...

  7. Python3基础-Python作用域详述(转载)

    转载文章 转载文章 作者:骏马金龙 出处:http://www.cnblogs.com/f-ck-need-u/p/9925021.html Python作用域详述 作用域是指变量的生效范围,例如本地 ...

  8. angualar入门学习-- 作用域$scope

    作用域$scope: 是ng执行环境,视图与controller之间的胶水,双向绑定的基础 $scope提供里$watch方法,监听数据模型变化 $scope提供里$apply方法,将数据模型变化更新 ...

  9. Python之路Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数

    Python之路Python作用域.匿名函数.函数式编程.map函数.filter函数.reduce函数 一.作用域 return 可以返回任意值例子 def test1(): print(" ...

随机推荐

  1. Android UI 开发

    今天主要学习了Android UI开发的几个知识 6大布局 样式和主题→自定义样式.主题 JUnit单元测试 Toast弹窗功能简介 6大布局 RelativeLayout LinearLayout ...

  2. ui-router的使用

    使用时需要ui中用ui-view指令指定 如: <div ui-view></div> 首先配置注册 ui-route var mainModule = angular.mod ...

  3. javascript 动态操作Html

    <html> <body> <p>aaaaa</p> <input type="button" value="con ...

  4. GET请求和POST请求

    A:有哪些get请求呢? a.在浏览器地址栏直接输入一个请求地址 b.点击超链接 c.表单默认的提交方式method="GET/get" B:get请求方式的特点 a.会将请求参数 ...

  5. html 中设置span的width完美解决方法

    在默认情况下,由于span是行标签,设置width是无效的.只有改变display的属性,才可以实现设置宽度. 1.初步想法 span{ background-color:#ccc; display: ...

  6. NSdate 时间格式

    NSdate 时间格式 NSTimeInterval 时间间隔 基本单位 秒 NSDateFormatter 时间格式器 用于日期对象的格式化或字符串解析为日期对象 日期格式如下: y  年 M  年 ...

  7. 编写类String的构造函数、拷贝构造函数、析构函数和赋值函数

    一.题目: class String { public: String(const char *str = NULL); // 普通构造函数 String(const String &othe ...

  8. 从内部剖析C#集合之HashTable

    计划写几篇文章专门介绍HashTable,Dictionary,HashSet,SortedList,List 等集合对象,从内部剖析原理,以便在实际应用中有针对性的选择使用. 这篇文章先介绍Hash ...

  9. 学习hamcrest和mockito时的总结和demo

    UT中需要的jar Junit4.1X.jar hamcrest-library-1.x.jar hamcrest-core-l.x.jar mockito-all-1.10.x.jar Junit ...

  10. configure: error: Cannot find libmysqlclient under /usr Note that the MySQL client library is not bundled anymore! 报错解决

    错误说明 今天在centos 6.3 64位版本上安装PHP5.4.3时在./configure 步骤的时候出现了下面错误configure: error: Cannot find libmysqlc ...