-
#!/usr/bin/env python
-
#-*- coding:utf8 -*-
-
#python对变量的操作都是在命名空间中(作用域),变量名被赋值的位置决定了这个变量名能被访问到的范围。
-
#变量赋值的地方决定了命名空间,即语义作用域。
-
#一个函数所有变量名都与函数的命名空间相关。
-
'''
-
def内定义的变量名只能在def内使用。
-
def内外的变量名不冲突。
-
变量对应的作用域: 作用于可以防止程序变量名冲突。
-
def内赋值就是def内。
-
嵌套def,对于嵌套函数是非本地。
-
def外赋值,是全局的。
-
'''
-
X=99#全局变量
-
def func():
-
X=88 #函数本地变量
-
#函数定义了本地作用哉,模块定义了全局作用域。
-
-
'''
-
内嵌的模块是全局作用域。
-
全局作用域的范围仅限单个文件。(全局是相对一个模块或文件而言。)
-
每次对函数的调用都创建了一个新的本地作用域。
-
赋值的变量名除非声明为全局变量或本地变量,否则均为本地变量。
-
所有其它的变量名都可以归纳为本地、全局、或都内置的。
-
此外,原处改变对象并不会把变量划分为本地变量,只有对变量名赋值才可以。即修改一个对象并不是对一个名称赋值。
-
'''
-
print('变量名解析:LEGB原则')
-
'''
-
变量名按:本地(L)->上层函数(E)->全局(G)->内置(B)的顺序查找
-
默认变量名赋值会创建或改变本地变量。(赋值总是创建或改变变量名,除非声明过类型。)
-
全局声明与非本地声明将赋值变量名映射到模块内部的作用域。
-
-
'''
-
#全局变量
-
X=99 #X与func在本模块中是:全局变量
-
def func(Y): #Y与Z在函数中是本地变量
-
#本地变量
-
Z=X+Y #X是全局变量
-
return Z
-
print(func(1))
-
#内置作用域 __builtin__ 内置模块
-
#import __builtin__
-
#print(dir(__builtin__))
-
-
#global语句
-
'''
-
全局变量是位于模块文件内部顶层的变量
-
全局变量在函数内必须经过声明
-
全局变量在函数内不用声明可以引用
-
'''
-
X=88 #全局变量
-
def func():
-
global X #全局变量声明
-
X=99
-
return X
-
print(func())
-
print(X)
-
-
a,b=1,2
-
def all_global():
-
global x
-
x=a+b
-
print(x)
-
all_global()
-
print(x)
-
#最小化全局变量
-
#原因是:流程控制比较难,保存状态信息过于复杂。
-
#最小化文件间的修改
-
#隐性的跨文件依赖性,在最好的情况下会导致代码不灵活,最坏的情况会引发bug。
-
-
import t17mod
-
t17mod.test()
-
#这个例子表明全局变量与模块的属性是等效的。但比global要多写许多语句。
-
-
-
-
-
'''
-
作用域和嵌套函数
-
'''
-
#按照LEGB法测,如果嵌套函数将一个变量声明为全局变量,它将改变整个模块作用域。如果我们只想想必被嵌套函数同为此变量名的变量的作用域,可以使用nonlocal声明,赋值会修改最近的嵌套函数中的变量的作用域
-
print('作用域和嵌套函数')
-
TT=99 #全局作用
-
def f1():
-
TT=88 #本地作用
-
def f2(): #f2是f1函数的本地变量
-
print(TT) #根据LEGB法则,X=88
-
f2()
-
f1()
-
-
#工厂函数,一个能记住嵌套作用域的变量值的函数,虽然有可能那个作用域已经不存在了。但类是最适合做记忆状态的。
-
#本地作用域中N被作为执行的状态信息保留下来。
-
def maker(N):
-
def action(M):
-
return N*M
-
return action
-
f = maker(5) #N=5
-
print(f(2)) #M=2,N是被记忆的为5
-
-
#新创建的函数不影响原来的
-
g=maker(9)
-
print(g(2))
-
print(f(2))
-
-
'''
-
尽量避免在def中内嵌套def。只要第二个函数定义在第一个函数调用前就可行。
-
如此可以避免使用嵌套
-
'''
-
def f1():
-
x=100
-
f2(x)
-
-
def f2(x):
-
print(x)
-
-
f1()
-
-
'''
-
嵌套作用域和lambda
-
lambda是一个表达式,但类似def,会生成新的作用域,可以使用在def不能使用的地方,如一个列表或是字典中
-
'''
-
def func(N):
-
action=(lambda M : N ** M)
-
return action
-
A=func(5)
-
print(A(2))
-
print(func(5)(3))
-
'''
-
作用域与带有循环变量的默认参数相比较
-
lambda或def函数在一个函数中定义,嵌套在一个循环中,并引用了上层函数的一个变量,变量在循环中被改变,但lambda或def函数最后值是最后一次循环后的值,不会受其它循环值影响
-
-
'''
-
def makeAction():
-
acts = []
-
for i in range(5):
-
acts.append(lambda n : i ** n )
-
return acts
-
actss=makeAction()
-
print(actss[2](2))
-
#因此必须把嵌套函数的值传递给嵌套作用域的变量
-
def makeAction2():
-
acts = []
-
for i in range(5):
-
acts.append(lambda n, i=i: i ** n)
-
return acts
-
actsss=makeAction2()
-
print(actsss[3](2))
-
#actsss[i]i最大不能超过range(5)的最大值。
-
print(actsss[4](2))
-
'''
-
作用域可以被任意嵌套,但是只有内嵌的函数会被搜索。
-
在python中,平坦优于嵌套。
-
'''
-
'''
-
nonlocal允许对嵌套函数作用域中的名称赋值,并且把这样的名称作用域查找限制在嵌套def.
-
'''
-
def tester(start):
-
state=start
-
def nester(label):
-
#默认不允许修改嵌套的def作用域中的名称。
-
#state +=1 #UnboundLocalError: local variable 'state' referenced before assignment
-
#python3.0中使用nonlocal修改,前提是nonlocal的变量在上层函数中已经赋值过。
-
#nonlocal只在上层函数的作用域中查找变量,不会去其它作用域查找。
-
#nonlocal state
-
#nonlocal nostate #SyntaxError: no binding for nonlocal 'nostate' found
-
print(label,state)
-
#state +=50
-
return nester
-
F=tester(100)
-
F(111) #111 100
-
F(112) #112 150
-
#如果创建一个新的副本,不会影响原来的state
-
G=tester(10)
-
G('egg') #egg 10
-
G('egg2') #egg2 60
-
F('old') #old 200
-
states2 = 9
-
def tester2(start):
-
def nester2(lable):
-
global states2
-
states2 = 99
-
print(lable,states2)
-
-
return nester2
-
H=tester2(1000)
-
H('new') #new 99
-
#nonlocal语句允许在内在保持可变状态的多个副本,并且解决了在类无法保证的情况下的简单的状态保持。
-
#下面使用类实现存状态保持。
-
class ctest:
-
def __init__(self,A):
-
self.state = A
-
def funcA(self,label):
-
print(label,self.state)
-
self.state +=1
-
CL=ctest(88)
-
CL.funcA('egg') #('egg', 88)
-
CL.funcA('egg2') #('egg2', 89)
-
print(CL.state) #90
-
#使用__call__运算符重载工具获取一个实例上的直接调用
-
class ct:
-
def __init__(self,A):
-
self.state = A
-
def __call__(self,label):
-
print(label,self.state)
-
self.state +=11
-
CL1=ct(77)
-
CL1('python') #('python', 77)
-
CL1('ADD11') #('ADD11', 88)
-
-
#下面这个没搞通,再研究了。
-
'''
-
def Z(start):
-
def Y(lable):
-
print(lable,Y.state)
-
Y.state += 1
-
Y.state = start
-
return Y
-
X=Z(188)
-
X('egg')
-
'''
-
'''
-
全局、非本地、类、函数属性都提供了状态保持选项。
-
全局只支持共享数据,类要用OOP知识,类和函数属性都允许嵌套自身之外访问状态。最好的工具取决于程序的目的。
-
'''
t17mod.py
-
#!/usr/bin/env python
-
#coding:utf8
-
var=99 #全局变量=模块属性
-
def local():
-
var = 0 #本地变量,不影响
-
def glob1():
-
global var #全局变量
-
var +=1 #修改全局var=100
-
def glob2():
-
var =0
-
import t17mod #导入模块,变成模块属性
-
t17mod.var +=1
-
def glob3():
-
var = 0
-
import sys
-
glob = sys.modules['t17mod'] #对模块属性生新赋值
-
glob.var +=1
-
def test():
-
print(var)
-
local();glob1();glob2();glob3() #按照执行顺序,第一个函数不影响全局变量
-
print(var)
结果
-
/usr/bin/python2.7 /home/talen/PycharmProjects/untitled/t17.py
-
变量名解析:LEGB原则
-
100
-
99
-
99
-
3
-
3
-
99
-
102
-
作用域和嵌套函数
-
88
-
10
-
18
-
10
-
100
-
25
-
125
-
16
-
9
-
16
-
(111, 100)
-
(112, 100)
-
('egg', 10)
-
('egg2', 10)
-
('old', 100)
-
('new', 99)
-
('egg', 88)
-
('egg2', 89)
-
90
-
('python', 77)
-
('ADD11', 88)
-
-
Process finished with exit code 0
阅读(1061) | 评论(0) | 转发(0) |