python学习手册17 作用域

简介: 点击(此处)折叠或打开 #!/usr/bin/env python #-*- coding:utf8 -*- #python对变量的操作都是在命名空间中(作用域),变量名被赋值的位置决定了这个变量名能被访问到的范围。

点击(此处)折叠或打开

  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. X=99#全局变量
  15. def func():
  16.     X=88 #函数本地变量
  17. #函数定义了本地作用哉,模块定义了全局作用域。

  18. '''
  19. 内嵌的模块是全局作用域。
  20. 全局作用域的范围仅限单个文件。(全局是相对一个模块或文件而言。)
  21. 每次对函数的调用都创建了一个新的本地作用域。
  22. 赋值的变量名除非声明为全局变量或本地变量,否则均为本地变量。
  23. 所有其它的变量名都可以归纳为本地、全局、或都内置的。
  24. 此外,原处改变对象并不会把变量划分为本地变量,只有对变量名赋值才可以。即修改一个对象并不是对一个名称赋值。
  25. '''
  26. print('变量名解析:LEGB原则')
  27. '''
  28. 变量名按:本地(L)->上层函数(E)->全局(G)->内置(B)的顺序查找
  29. 默认变量名赋值会创建或改变本地变量。(赋值总是创建或改变变量名,除非声明过类型。)
  30. 全局声明与非本地声明将赋值变量名映射到模块内部的作用域。

  31. '''
  32. #全局变量
  33. X=99 #X与func在本模块中是:全局变量
  34. def func(Y): #Y与Z在函数中是本地变量
  35.     #本地变量
  36.     Z=X+Y #X是全局变量
  37.     return Z
  38. print(func(1))
  39. #内置作用域 __builtin__ 内置模块
  40. #import __builtin__
  41. #print(dir(__builtin__))

  42. #global语句
  43. '''
  44. 全局变量是位于模块文件内部顶层的变量
  45. 全局变量在函数内必须经过声明
  46. 全局变量在函数内不用声明可以引用
  47. '''
  48. X=88 #全局变量
  49. def func():
  50.     global X #全局变量声明
  51.     X=99
  52.     return X
  53. print(func())
  54. print(X)

  55. a,b=1,2
  56. def all_global():
  57.     global x
  58.     x=a+b
  59.     print(x)
  60. all_global()
  61. print(x)
  62. #最小化全局变量
  63. #原因是:流程控制比较难,保存状态信息过于复杂。
  64. #最小化文件间的修改
  65. #隐性的跨文件依赖性,在最好的情况下会导致代码不灵活,最坏的情况会引发bug。

  66. import t17mod
  67. t17mod.test()
  68. #这个例子表明全局变量与模块的属性是等效的。但比global要多写许多语句。




  69. '''
  70. 作用域和嵌套函数
  71. '''
  72. #按照LEGB法测,如果嵌套函数将一个变量声明为全局变量,它将改变整个模块作用域。如果我们只想想必被嵌套函数同为此变量名的变量的作用域,可以使用nonlocal声明,赋值会修改最近的嵌套函数中的变量的作用域
  73. print('作用域和嵌套函数')
  74. TT=99 #全局作用
  75. def f1():
  76.     TT=88 #本地作用
  77.     def f2(): #f2是f1函数的本地变量
  78.         print(TT) #根据LEGB法则,X=88
  79.     f2()
  80. f1()

  81. #工厂函数,一个能记住嵌套作用域的变量值的函数,虽然有可能那个作用域已经不存在了。但类是最适合做记忆状态的。
  82. #本地作用域中N被作为执行的状态信息保留下来。
  83. def maker(N):
  84.     def action(M):
  85.         return N*M
  86.     return action
  87. f = maker(5) #N=5
  88. print(f(2)) #M=2,N是被记忆的为5

  89. #新创建的函数不影响原来的
  90. g=maker(9)
  91. print(g(2))
  92. print(f(2))

  93. '''
  94. 尽量避免在def中内嵌套def。只要第二个函数定义在第一个函数调用前就可行。
  95. 如此可以避免使用嵌套
  96. '''
  97. def f1():
  98.     x=100
  99.     f2(x)

  100. def f2(x):
  101.     print(x)

  102. f1()

  103. '''
  104. 嵌套作用域和lambda
  105.     lambda是一个表达式,但类似def,会生成新的作用域,可以使用在def不能使用的地方,如一个列表或是字典中
  106. '''
  107. def func(N):
  108.     action=(lambda M : N ** M)
  109.     return action
  110. A=func(5)
  111. print(A(2))
  112. print(func(5)(3))
  113. '''
  114. 作用域与带有循环变量的默认参数相比较
  115.     lambda或def函数在一个函数中定义,嵌套在一个循环中,并引用了上层函数的一个变量,变量在循环中被改变,但lambda或def函数最后值是最后一次循环后的值,不会受其它循环值影响

  116. '''
  117. def makeAction():
  118.     acts = []
  119.     for i in range(5):
  120.         acts.append(lambda n : i ** n )
  121.     return acts
  122. actss=makeAction()
  123. print(actss[2](2))
  124. #因此必须把嵌套函数的值传递给嵌套作用域的变量
  125. def makeAction2():
  126.     acts = []
  127.     for i in range(5):
  128.         acts.append(lambda n, i=i: i ** n)
  129.     return acts
  130. actsss=makeAction2()
  131. print(actsss[3](2))
  132. #actsss[i]i最大不能超过range(5)的最大值。
  133. print(actsss[4](2))
  134. '''
  135. 作用域可以被任意嵌套,但是只有内嵌的函数会被搜索。
  136.     在python中,平坦优于嵌套。
  137. '''
  138. '''
  139. nonlocal允许对嵌套函数作用域中的名称赋值,并且把这样的名称作用域查找限制在嵌套def.
  140. '''
  141. def tester(start):
  142.     state=start
  143.     def nester(label):
  144.         #默认不允许修改嵌套的def作用域中的名称。
  145.         #state +=1 #UnboundLocalError: local variable 'state' referenced before assignment
  146.         #python3.0中使用nonlocal修改,前提是nonlocal的变量在上层函数中已经赋值过。
  147.         #nonlocal只在上层函数的作用域中查找变量,不会去其它作用域查找。
  148.         #nonlocal state
  149.         #nonlocal nostate #SyntaxError: no binding for nonlocal 'nostate' found
  150.         print(label,state)
  151.         #state +=50
  152.     return nester
  153. F=tester(100)
  154. F(111) #111 100
  155. F(112) #112 150
  156. #如果创建一个新的副本,不会影响原来的state
  157. G=tester(10)
  158. G('egg') #egg 10
  159. G('egg2') #egg2 60
  160. F('old') #old 200
  161. states2 = 9
  162. def tester2(start):
  163.     def nester2(lable):
  164.         global states2
  165.         states2 = 99
  166.         print(lable,states2)

  167.     return nester2
  168. H=tester2(1000)
  169. H('new') #new 99
  170. #nonlocal语句允许在内在保持可变状态的多个副本,并且解决了在类无法保证的情况下的简单的状态保持。
  171. #下面使用类实现存状态保持。
  172. class ctest:
  173.     def __init__(self,A):
  174.         self.state = A
  175.     def funcA(self,label):
  176.         print(label,self.state)
  177.         self.state +=1
  178. CL=ctest(88)
  179. CL.funcA('egg') #('egg', 88)
  180. CL.funcA('egg2') #('egg2', 89)
  181. print(CL.state) #90
  182. #使用__call__运算符重载工具获取一个实例上的直接调用
  183. class ct:
  184.     def __init__(self,A):
  185.         self.state = A
  186.     def __call__(self,label):
  187.         print(label,self.state)
  188.         self.state +=11
  189. CL1=ct(77)
  190. CL1('python') #('python', 77)
  191. CL1('ADD11') #('ADD11', 88)

  192. #下面这个没搞通,再研究了。
  193. '''
  194. def Z(start):
  195.     def Y(lable):
  196.     print(lable,Y.state)
  197.     Y.state += 1
  198.     Y.state = start
  199.     return Y
  200. X=Z(188)
  201. X('egg')
  202. '''
  203. '''
  204. 全局、非本地、类、函数属性都提供了状态保持选项。
  205. 全局只支持共享数据,类要用OOP知识,类和函数属性都允许嵌套自身之外访问状态。最好的工具取决于程序的目的。
  206. '''


t17mod.py

点击(此处)折叠或打开

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


目录
相关文章
Python学习的自我理解和想法(9)
这是我在B站跟随千锋教育学习Python的第9天,主要学习了赋值、浅拷贝和深拷贝的概念及其底层逻辑。由于开学时间紧张,内容较为简略,但希望能帮助理解这些重要概念。赋值是创建引用,浅拷贝创建新容器但元素仍引用原对象,深拷贝则创建完全独立的新对象。希望对大家有所帮助,欢迎讨论。
1.1 学习Python操作Excel的必要性
学习Python操作Excel在当今数据驱动的商业环境中至关重要。Python能处理大规模数据集,突破Excel行数限制;提供丰富的库实现复杂数据分析和自动化任务,显著提高效率。掌握这项技能不仅能提升个人能力,还能为企业带来价值,减少人为错误,提高决策效率。推荐从基础语法、Excel操作库开始学习,逐步进阶到数据可视化和自动化报表系统。通过实际项目巩固知识,关注新技术,为职业发展奠定坚实基础。
Python学习的自我理解和想法(10)
这是我在千锋教育B站课程学习Python的第10天笔记,主要学习了函数的相关知识。内容包括函数的定义、组成、命名、参数分类(必须参数、关键字参数、默认参数、不定长参数)及调用注意事项。由于开学时间有限,记录较为简略,望谅解。通过学习,我理解了函数可以封装常用功能,简化代码并便于维护。若有不当之处,欢迎指正。
Python学习的自我理解和想法(6)
这是我在B站千锋教育学习Python的第6天笔记,主要学习了字典的使用方法,包括字典的基本概念、访问、修改、添加、删除元素,以及获取字典信息、遍历字典和合并字典等内容。开学后时间有限,内容较为简略,敬请谅解。
Python学习的自我理解和想法(2)
今日学习Python第二天,重点掌握字符串操作。内容涵盖字符串介绍、切片、长度统计、子串计数、大小写转换及查找位置等。通过B站黑马程序员课程跟随老师实践,非原创代码,旨在巩固基础知识与技能。
Python学习的自我理解和想法(3)
这是学习Python第三天的内容总结,主要围绕字符串操作展开,包括字符串的提取、分割、合并、替换、判断、编码及格式化输出等,通过B站黑马程序员课程跟随老师实践,非原创代码。
Python学习的自我理解和想法(7)
学的是b站的课程(千锋教育),跟老师写程序,不是自创的代码! 今天是学Python的第七天,学的内容是集合。开学了,时间不多,写得不多,见谅。
Python学习的自我理解和想法(8)
这是我在B站千锋教育学习Python的第8天,主要内容是元组。元组是一种不可变的序列数据类型,用于存储一组有序的元素。本文介绍了元组的基本操作,包括创建、访问、合并、切片、遍历等,并总结了元组的主要特点,如不可变性、有序性和可作为字典的键。由于开学时间紧张,内容较为简略,望见谅。
Python学习的自我理解和想法(4)
今天是学习Python的第四天,主要学习了列表。列表是一种可变序列类型,可以存储任意类型的元素,支持索引和切片操作,并且有丰富的内置方法。主要内容包括列表的入门、关键要点、遍历、合并、判断元素是否存在、切片、添加和删除元素等。通过这些知识点,可以更好地理解和应用列表这一强大的数据结构。
Python学习的自我理解和想法(5)
这是我在B站千锋教育学习Python的第五天笔记,主要内容包括列表的操作,如排序(`sort()`、``sorted()``)、翻转(`reverse()`)、获取长度(`len()`)、最大最小值(`max()`、``min()``)、索引(`index()`)、嵌套列表和列表生成(`range`、列表生成式)。通过这些操作,可以更高效地处理数据。希望对大家有所帮助!
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等