1. #!/usr/bin/env python
2. -*- coding:utf8 -*-
3.  #python对变量的操作都是在命名空间中(作用域),变量名被赋值的位置决定了这个变量名能被访问到的范围。
4.  #变量赋值的地方决定了命名空间,即语义作用域。
5.  #一个函数所有变量名都与函数的命名空间相关。
6. '''
7.  def内定义的变量名只能在def内使用。
8.  def内外的变量名不冲突。
9.  变量对应的作用域: 作用于可以防止程序变量名冲突。
10.      def内赋值就是def内。
11.      嵌套def,对于嵌套函数是非本地。
12.      def外赋值,是全局的。
13. ''
14. =99#全局变量
15. ():
16. =88 #函数本地变量
17.  #函数定义了本地作用哉,模块定义了全局作用域。
18.  
19. '''
20.  内嵌的模块是全局作用域。
21.  全局作用域的范围仅限单个文件。(全局是相对一个模块或文件而言。)
22.  每次对函数的调用都创建了一个新的本地作用域。
23.  赋值的变量名除非声明为全局变量或本地变量,否则均为本地变量。
24.  所有其它的变量名都可以归纳为本地、全局、或都内置的。
25.  此外,原处改变对象并不会把变量划分为本地变量,只有对变量名赋值才可以。即修改一个对象并不是对一个名称赋值。
26. ''
27. ('变量名解析:LEGB原则')
28. '''
29.  变量名按:本地(L)->上层函数(E)->全局(G)->内置(B)的顺序查找
30.  默认变量名赋值会创建或改变本地变量。(赋值总是创建或改变变量名,除非声明过类型。)
31.  全局声明与非本地声明将赋值变量名映射到模块内部的作用域。
32.  
33. ''
34.  #全局变量
35. =99 #X与func在本模块中是:全局变量
36. (Y): #Y与Z在函数中是本地变量
37.      #本地变量
38. =X+Y #X是全局变量
39.      return Z
40. (func(1))
41.  #内置作用域 __builtin__ 内置模块
42.  #import __builtin__
43. (dir(__builtin__))
44.  
45.  #global语句
46. '''
47.  全局变量是位于模块文件内部顶层的变量
48.  全局变量在函数内必须经过声明
49.  全局变量在函数内不用声明可以引用
50. ''
51. =88 #全局变量
52. ():
53.      global X #全局变量声明
54. =99
55.      return X
56. (func())
57. (X)
58.  
59. ,b=1,2
60. ():
61.      global x
62. =a+b
63. (x)
64. ()
65. (x)
66.  #最小化全局变量
67.  #原因是:流程控制比较难,保存状态信息过于复杂。
68.  #最小化文件间的修改
69.  #隐性的跨文件依赖性,在最好的情况下会导致代码不灵活,最坏的情况会引发bug。
70.  
71.  import t17mod
72. .test()
73.  #这个例子表明全局变量与模块的属性是等效的。但比global要多写许多语句。
74.  
75.  
76.  
77.  
78. '''
79.  作用域和嵌套函数
80. ''
81.  #按照LEGB法测,如果嵌套函数将一个变量声明为全局变量,它将改变整个模块作用域。如果我们只想想必被嵌套函数同为此变量名的变量的作用域,可以使用nonlocal声明,赋值会修改最近的嵌套函数中的变量的作用域
82. ('作用域和嵌套函数')
83. =99 #全局作用
84. ():
85. =88 #本地作用
86. (): #f2是f1函数的本地变量
87. (TT) #根据LEGB法则,X=88
88. ()
89. ()
90.  
91.  #工厂函数,一个能记住嵌套作用域的变量值的函数,虽然有可能那个作用域已经不存在了。但类是最适合做记忆状态的。
92.  #本地作用域中N被作为执行的状态信息保留下来。
93. (N):
94. (M):
95. *M
96.      return action
97. = maker(5) #N=5
98. (f(2)) #M=2,N是被记忆的为5
99.  
100.  #新创建的函数不影响原来的
101. =maker(9)
102. (g(2))
103. (f(2))
104.  
105. '''
106.  尽量避免在def中内嵌套def。只要第二个函数定义在第一个函数调用前就可行。
107.  如此可以避免使用嵌套
108. ''
109. ():
110. =100
111. (x)
112.  
113. (x):
114. (x)
115.  
116. ()
117.  
118. '''
119.  嵌套作用域和lambda
120.      lambda是一个表达式,但类似def,会生成新的作用域,可以使用在def不能使用的地方,如一个列表或是字典中
121. ''
122. (N):
123. =(lambda M : N ** M)
124.      return action
125. =func(5)
126. (A(2))
127. (func(5)(3))
128. '''
129.  作用域与带有循环变量的默认参数相比较
130.      lambda或def函数在一个函数中定义,嵌套在一个循环中,并引用了上层函数的一个变量,变量在循环中被改变,但lambda或def函数最后值是最后一次循环后的值,不会受其它循环值影响
131.  
132. ''
133. ():
134. = []
135. for i in range(5):
136. .append(lambda n : i ** n )
137.      return acts
138. =makeAction()
139. (actss[2](2))
140.  #因此必须把嵌套函数的值传递给嵌套作用域的变量
141. ():
142. = []
143. for i in range(5):
144. .append(lambda n, i=i: i ** n)
145.      return acts
146. =makeAction2()
147. (actsss[3](2))
148. [i]i最大不能超过range(5)的最大值。
149. (actsss[4](2))
150. '''
151.  作用域可以被任意嵌套,但是只有内嵌的函数会被搜索。
152.      在python中,平坦优于嵌套。
153. ''
154. '''
155.  nonlocal允许对嵌套函数作用域中的名称赋值,并且把这样的名称作用域查找限制在嵌套def.
156. ''
157. (start):
158. =start
159. (label):
160.          #默认不允许修改嵌套的def作用域中的名称。
161. +=1 #UnboundLocalError: local variable 'state' referenced before assignment
162. .0中使用nonlocal修改,前提是nonlocal的变量在上层函数中已经赋值过。
163.          #nonlocal只在上层函数的作用域中查找变量,不会去其它作用域查找。
164.          #nonlocal state
165. : no binding for nonlocal 'nostate' found
166. (label,state)
167. +=50
168.      return nester
169. =tester(100)
170. (111) #111 100
171. (112) #112 150
172.  #如果创建一个新的副本,不会影响原来的state
173. =tester(10)
174. ('egg') #egg 10
175. ('egg2') #egg2 60
176. ('old') #old 200
177. = 9
178. (start):
179. (lable):
180.          global states2
181. = 99
182. (lable,states2)
183.  
184.      return nester2
185. =tester2(1000)
186. ('new') #new 99
187.  #nonlocal语句允许在内在保持可变状态的多个副本,并且解决了在类无法保证的情况下的简单的状态保持。
188.  #下面使用类实现存状态保持。
189. :
190. (self,A):
191. .state = A
192. (self,label):
193. (label,self.state)
194. .state +=1
195. CL=ctest(88)
196. CL.funcA('egg') #('egg', 88)
197. CL.funcA('egg2') #('egg2', 89)
198. (CL.state) #90
199.  #使用__call__运算符重载工具获取一个实例上的直接调用
200. :
201. (self,A):
202. .state = A
203. (self,label):
204. (label,self.state)
205. .state +=11
206. =ct(77)
207. ('python') #('python', 77)
208. ('ADD11') #('ADD11', 88)
209.  
210.  #下面这个没搞通,再研究了。
211. '''
212.  def Z(start):
213.      def Y(lable):
214.      print(lable,Y.state)
215.      Y.state += 1
216.      Y.state = start
217.      return Y
218.  X=Z(188)
219. ')
220. ''
221. '''
222.  全局、非本地、类、函数属性都提供了状态保持选项。
223.  全局只支持共享数据,类要用OOP知识,类和函数属性都允许嵌套自身之外访问状态。最好的工具取决于程序的目的。
224. ''




t17mod.py



此处)折叠或打开


1. #!/usr/bin/env python
2. :utf8
3. =99 #全局变量=模块属性
4. local():
5. = 0 #本地变量,不影响
6. ():
7.      global var #全局变量
8. +=1 #修改全局var=100
9. ():
10. =0
11.      import t17mod #导入模块,变成模块属性
12. .var +=1
13. ():
14. = 0
15.      import sys
16. = sys.modules['t17mod'] #对模块属性生新赋值
17. .var +=1
18. test():
19. (var)
20. local();glob1();glob2();glob3() #按照执行顺序,第一个函数不影响全局变量
21. (var)

结果



此处)折叠或打开


1. /usr/bin/python2.7 /home/talen/PycharmProjects/untitled/t17.py
2.  变量名解析:LEGB原则
3.  100
4.  99
5.  99
6.  3
7.  3
8.  99
9.  102
10.  作用域和嵌套函数
11.  88
12.  10
13.  18
14.  10
15.  100
16.  25
17.  125
18.  16
19.  9
20.  16
21. (111, 100)
22. (112, 100)
23. ('egg', 10)
24. ('egg2', 10)
25. ('old', 100)
26. ('new', 99)
27. ('egg', 88)
28. ('egg2', 89)
29.  90
30. ('python', 77)
31. ('ADD11', 88)
32.  
33.  Process finished with exit code 0