可以先看: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. SSH公钥(public key)验证

    安全的设置服务器 登陆,之前用用户名和密码登陆服务器 这样不安全 ,用SSH公钥(public key)验证  这个办法能很好的解决 登陆服务器 和安全登陆服务器 的特点: 目标: Client 免输 ...

  2. 在用VS2010连接oracle数据库时ORA-12504错误

    在用VS2010连接oracle数据库时,可能会出现: ORA-12504: TNS: 监听程序在 CONNECT_DATA 中未获得 SERVICE_NAME 只需在web.config文件Data ...

  3. 手机端的表单验证和PC端的不同

    1.手机端:由于页面小的局限性,表单验证从上到下依次进行,如果上一个验证不通过,则给出错误提示,代码中return回去,不必进行下一个的校验: 2.PC端:页面范围大,一般是在表单的后面或者下面,提示 ...

  4. C# Ref 与out 的区别

    在C#中,有四种传递参数方式: 1. 传值 (value) : 无额外修饰符 2. 传址(reference) : 需修饰符Ref,传入函数的参数必须先赋值 3. 输出参数(output): 需修饰符 ...

  5. oracle 权限管理

    系统权限 系统权限需要授予者有进行系统级活动的能力,如连接数据库,更改用户会话.建立表或建立用户等等.你可以在数据字典视图SYSTEM_PRIVILEGE_MAP上获得完整的系统权限.对象权限和系统权 ...

  6. 判断ios是app第一次启动

    首次运行的应用程序加入一些help 或者 宣传动画 现在变的很重要了. 一个有用的例子是发送一个分析实例.这可能是一个很好的方法来确定有多少人下载实用应用程序.有人会说:“但是,嘿,苹果AppStor ...

  7. 使用ArrayList对大小写字母的随机打印

    从a~z以及A~Z随机生成一个字母并打印:打印全部的字母 package com.liaojianya.chapter1; import java.util.ArrayList; /** * This ...

  8. PHP Ajax简单实例

    最近学习Jquery Ajax部分,通过简单例子,比较了下post,get方法的不同 HTML部分 <html> <head> <title>jQuery Ajax ...

  9. js获取星期几

    function getweek(time) { /*显示星期*/ /*time为date格式*/ var str; var d = time.getDay(); switch (d) { case ...

  10. Android中基于Socket的网络通信

    1. Socket介绍 2. ServerSocket的建立与使用 3. 使用ServerSocket建立聊天服务器-1 4. 使用ServerSocket建立聊天服务器-2 5. 在Android中 ...