博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python入门篇-返回值和作用域
阅读量:7091 次
发布时间:2019-06-28

本文共 11477 字,大约阅读时间需要 38 分钟。

              Python入门篇-返回值和作用域

                                      作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

 

 

 

 

一.返回值

1>.返回值概述

Python函数使用return语句返回“返回值” 所有函数都有返回值,如果没有return语句,隐式调用return None return 语句并不一定是函数的语句块的最后一条语句 一个函数可以存在多个return语句,但是只有一条可以被执行。如果没有一条return语句被执行到,隐式调用return None 如果有必要,可以显示调用return None,可以简写为return 如果函数执行了return语句,函数就会返回,当前被执行的return语句之后的其它语句就不会被执行了 作用:结束函数调用、返回值

2>.函数单个值

1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6  7  8 def show(x): 9     for i in  range(x):10         if i > 3:11             return i12         else:13             print("{} is not greater than 3".format(i))14 15 16 res1 = show(3)17 18 print("*" * 20 + "我是分隔符" + "*" * 20)19 20 res2 = show(5)21 22 print("res1 = {}".format(res1))23 print("res2 = {}".format(res2))24 25 26 27 #以上代码执行结果如下:28 0 is not greater than 329 1 is not greater than 330 2 is not greater than 331 ********************我是分隔符********************32 0 is not greater than 333 1 is not greater than 334 2 is not greater than 335 3 is not greater than 336 res1 = None37 res2 = 4

3>.返回多个值

#!/usr/bin/env python#_*_coding:utf-8_*_#@author :yinzhengjie#blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/#EMAIL:y1053419035@qq.com"""    函数不能同时返回多个值,但是可用返回一个列表或者一个元组""""""    是指明返回一个列表,是一个列表对象"""def returnList():    return [1,3,5]"""    看似返回多个值,隐式的被python封装成了一个元组"""def returnTuple():    return [2,4,6]x,y,z = returnList()        #使用解构提取更为方便m,n,l = returnTuple()print(x,y,z,m,n,l)#以上代码执行结果如下:1 3 5 2 4 6

 

二.作用域

1>.作用域概述

作用域:    一个标识符的可见范围,这就是标识符的作用域。一般常说的是变量的作用域全局作用域    在整个程序运行环境中都可见局部作用域    在函数、类等内部可见    局部变量使用范围不能超过其所在的局部作用域

2>.嵌套结构观察作用域变化

1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6  7  8 """ 9     外层变量作用域在内层作用域可见10 """11 def outer1():12     o = 6513     def inner():14         print("inner {}".format(o))15         print(chr(o))16     print("outer {}".format(o))17     inner()18 19 """20     内层作用域inner中,如果定义了o=97,相当于当前作用域中重新定义了一个新的变量o,但是这个o并没有覆盖外层作用域outer中的o21 """22 def outer2(): #23     o = 6524     def inner():25         o = 9726         print("inner {}".format(o))27         print(chr(o))28     print("outer {}".format(o))29     inner()30 31 outer1()32 33 print("*" * 20 + "我是分隔符" + "*" * 20)34 35 outer2()36 37 38 39 #以上代码执行结果如下:40 outer 6541 inner 6542 A43 ********************我是分隔符********************44 outer 6545 inner 9746 a

3>.赋值定义注意事项

#!/usr/bin/env python#_*_coding:utf-8_*_#@author :yinzhengjie#blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/#EMAIL:y1053419035@qq.comx = 10          #全局作用域变量xdef foo():    """        “y = x + 1”这一行代码引用了全局作用域的x变量。    """    y = x + 10    """        这一行代码会抛异常:“UnboundLocalError: local variable 'x' referenced before assignment”。        原因就是赋值定义导致的,“x += 1”其实是“x = x + 1”,相当于在foo内部定义一个局部变量x,        那么foo内部所有x都是这个局部变量x了,但是这个x还没有完成赋值,就被右边拿来做加1操作了,因此才会抛出该异常        简单的说,就是在定义x变量之前我们已经对该变量做了引用导致的报错。如何解决这个问题?我们可以引入全局变量global.    """    # x += 1    print(x,y)foo()#以上代码输出结果如下:10 20

4>.在局部变量修改全局变量

#!/usr/bin/env python#_*_coding:utf-8_*_#@author :yinzhengjie#blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/#EMAIL:y1053419035@qq.comx = 5"""    使用global关键字的变量,将foo内的x声明为使用外部的全局作用域中定义的x    全局作用域中必须有x的定义,如果全局作用域中没有定义x变量,则会报错:“NameError: name 'x' is not defined”"""def foo():    global x    print("foo() : x = {}".format(x))    x += 10    print("foo() : x = {}".format(x))print("调用foo()函数之前:x = {}".format(x))foo()print("调用foo()函数之后:x = {}".format(x))#以上代码输出结果如下:调用foo()函数之前:x = 5foo() : x = 5foo() : x = 15调用foo()函数之后:x = 15

5>. 在局部变量中声明全局变量

1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6  7  8 def foo(): 9     global x        #使用global关键字的变量,将foo内的x声明为使用外部的全局作用域中定义的x10     x = 10          #x = 10 赋值即定义,在内部作用域为一个外部作用域的变量x赋值,不是在内部作用域定义一个新变量,所以x+=1不会报错。注意,这里x的作用域还是全局的11     x += 2012     print(x)13 14 foo()15 16 print(x)        #注意,这个打印x变量一定要在先调用foo()函数,因为只有调用了foo()函数才会触发生成全局变量x,否则会抛异常:"NameError: name 'x' is not defined"17 18 19 20 #以上代码输出结果如下:21 3022 30

6>.global总结

x+=1这种是特殊形式产生的错误的原因?先引用后赋值,而python动态语言是赋值才算定义,才能被引用。解决办法,在这条语句前增加x=0之类的赋值语句,或者使用global告诉内部作用域,去全局作用域查找变量定义 内部作用域使用x = 5之类的赋值语句会重新定义局部作用域使用的变量x,但是,一旦这个作用域中使用global声明x为全局的,那么x=5相当于在为全局作用域的变量x赋值

7>.global使用原则

外部作用域变量会内部作用域可见,但也不要在这个内部的局部作用域中直接使用,因为函数的目的就是为了封装,尽量与外界隔离 如果函数需要使用外部全局变量,请使用函数的形参传参解决 一句话:不用global。学习它就是为了深入理解变量作用域.

 

三.闭包 

1>.闭包概述

自由变量:未在本地作用域中定义的变量。例如定义在内层函数外的外层函数的作用域中的变量 闭包:就是一个概念,出现在嵌套函数中,指的是内层函数引用到了外层函数的自由变量,就形成了闭包。很多语言都有这个概念,最熟悉就是JavaScript

2>.闭包函数案例(这是Python2中实现闭包的方式,Python3还可以使用nonlocal关键字

1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6  7  8 def counter(): 9     c = [0]10     def inc():11         c[0] += 10          #注意,这行代码c[0] = c[0] + 10,这样操作并不会报错,因为并没有修改变量c,而是修改的c中的一个引用。12         return c[0]13     return inc              #返回的是c变量的一个引用,即c[0]14 15 foo = counter()16 17 print(foo(),foo())          #每调用次都会对c[0] 对象加10,因此每次调用的结果不会发生改变18 19 c = 100                     #此处我们定了一个变量c,但对c[0]并不会产生印象哟,因此下面的操作依旧会对c[0]加10.20 21 print(foo())              22 23 24 25 #以上代码执行结果如下:26 10 2027 30

3>.nonlocal关键字

1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6  7  8  9 """10     使用了nonlocal关键字,将变量标记为不在本地作用域定义,而在上级的某一级局部作用域中定义,但不能是全局作用域中定义11     count 是外层函数的局部变量,被内部函数引用12     内部函数使用nonlocal关键字声明count变量在上级作用域而非本地作用域中定义13 """14 15 def counter():16     count = 017     def inc():18         nonlocal count19         count += 1020         return count21     return inc22 23 foo = counter()24 25 print(foo())26 print(foo())27 28 29 30 #以上代码执行结果如下:31 1032 20

 

四.默认值的作用域

1>.默认值的作用域

1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6  7 def foo(x=1): 8     return x 9 10 def bar(y=[]):11     y.append(100)12     return y13 14 print("foo():{}, ID:{}\n".format(foo(),id(foo())))15 print("foo():{}, ID:{}\n".format(foo(),id(foo())))16 17 # print(x)        #报错:NameError: name 'x' is not defined,即形参的作用域数据函数的局部变量18 19 print("bar():{}, ID:{}\n".format(bar(),id(bar())))20 print("bar():{}, ID:{}\n".format(bar(),id(bar())))21 22 """23 为什么第二次调用foo函数打印的是[100,100]?24     因为函数也是对象,python把函数的默认值放在了属性中,这个属性就伴随着这个函数对象的整个生命周期25     查看bar.__defaults__属性26 """27 print("bar.__defaults__:{}".format(bar.__defaults__))28 29 30 31 #以上代码执行结果如下:32 foo():1, ID:163888643233 34 foo():1, ID:163888643235 36 bar():[100, 100], ID:4294765637 38 bar():[100, 100, 100, 100], ID:4294765639 40 bar.__defaults__:([100, 100, 100, 100],)

2>.非引用类型例子

1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6  7  8 def foo(w, u='yzj', *, z=123, zz=[456]): 9     u = 'jason'10     z = 201911     zz.append(1)12     print(w, u, z, zz)13 14 print(foo.__defaults__)        #属性__defaults__中使用元组保存所有位置参数默认值,它不会因为在函数体内使用了它而发生改变15 16 foo('node101.yinzhengjie.org.cn')17 18 print(foo.__kwdefaults__)       #属性__kwdefaults__中使用字典保存所有keyword-only参数的默认值19 20 21 22 #以上代码执行结果如下:23 ('yzj',)24 node101.yinzhengjie.org.cn jason 2019 [456, 1]25 {
'z': 123, 'zz': [456, 1]}

3>.使用影子拷贝创建一个新的对象,永远不能改变传入的参数

1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6  7 """ 8     使用影子拷贝创建一个新的对象,永远不能改变传入的参数 9 """10 def foo(x=[], y='jason', z=123):11     x = x[:]        # 影子拷贝12     x.append(1)     # x都是传入参数或者默认参数的副本,如果就想修改原参数,无能为力13     print(x)14 15 foo()16 print(foo.__defaults__)17 foo()18 print(foo.__defaults__)19 foo([10])20 print(foo.__defaults__)21 foo([10,5])22 print(foo.__defaults__)23 24 25 26 #以上代码执行结果如下:27 [1]28 ([], 'jason', 123)29 [1]30 ([], 'jason', 123)31 [10, 1]32 ([], 'jason', 123)33 [10, 5, 1]34 ([], 'jason', 123)

4>.使用不可变类型默认值

#!/usr/bin/env python#_*_coding:utf-8_*_#@author :yinzhengjie#blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/#EMAIL:y1053419035@qq.com"""    通过值的判断就可以灵活的选择创建或者修改传入对象    这种方式灵活,应用广泛    很多函数的定义,都可以看到使用None这个不可变的值作为默认参数,可以说这是一种惯用法"""def foo(x=None, y='jason', z=2019):    if x is None:        x = []    x.append(1)    print(x)foo()print(foo.__defaults__)foo()print(foo.__defaults__)foo([10])print(foo.__defaults__)foo([10,5])print(foo.__defaults__)#以上代码执行结果如下:[1](None, 'jason', 2019)[1](None, 'jason', 2019)[10, 1](None, 'jason', 2019)[10, 5, 1](None, 'jason', 2019)

 

五.变量名解析原则LEGB

 

Local,本地作用域、局部作用域的local命名空间。函数调用时创建,调用结束消亡 Enclosing,Python2.2时引入了嵌套函数,实现了闭包,这个就是嵌套函数的外部函数的命名空间 Global,全局作用域,即一个模块的命名空间。模块被import时创建,解释器退出时消亡 Build-in,内置模块的命名空间,生命周期从python解释器启动时创建到解释器退出时消亡。例如print(open),print和open都是内置的变量 所以一个名词的查找顺序就是LEGB 关于函数的执行流程,博主推荐链接:。

 

六.函数的销毁

1>.全局函数销毁

1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6  7  8 """ 9 全局函数销毁10     重新定义同名函数11     del 语句删除函数对象12     程序结束时13 """14 15 16 17 def foo(x=[], y='jason', z=123):18     x.append(100)19     return x20 21 print(foo(), id(foo), foo.__defaults__)22 23 def foo(x=[], y='jason', z=123):24     x.append(200)25     return x26 27 print(foo(), id(foo), foo.__defaults__)28 29 del foo30 31 # print(foo(), id(foo), foo.__defaults__)       #由于我们已经使用del关键字销毁了foo函数,执行该行代码会抛异常:"NameError: name 'foo' is not defined"32 33 34 35 #以上代码执行结果如下:36 [100] 4136608 ([100], 'jason', 123)37 [200] 35462136 ([200], 'jason', 123)

2>.局部函数销毁

1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6  7  8 """ 9 局部函数销毁10     重新在上级作用域定义同名函数11     del 语句删除函数名称,函数对象的引用计数减112     上级作用域销毁时13 """14 def foo(x=[], u='jason', z=2019):15     x.append(1)16     def inner(a=10):17         pass18     print(inner)19     def inner(a=100):20         print(x)21     print(inner)22     return inner23 24 25 bar = foo()26 print(id(foo),id(bar), foo.__defaults__, bar.__defaults__)27 del bar28 # print(id(foo),id(bar), foo.__defaults__, bar.__defaults__)         #由于我们已经使用del关键字销毁了bar函数,执行该行代码会抛异常:"NameError: name 'bar' is not defined"29 30 31 #以上代码执行结果如下:32 
.inner at 0x0000000001EB1BF8>33
.inner at 0x0000000001EB1C80>34 4923040 32185472 ([1], 'jason', 2019) (100,)

 

转载于:https://www.cnblogs.com/yinzhengjie/p/10960410.html

你可能感兴趣的文章
Gartner:DAM(数据库审计)正在向DAP(数据库审计与保护)演进
查看>>
数据库中的读一致性和脚本匹配
查看>>
ABAP ALV显示例子
查看>>
d3.js
查看>>
jflex1.5扫描中文字符
查看>>
mysql视图和临时表的区别
查看>>
在Linux操作系统下修改IP、DNS和路由配置
查看>>
我的友情链接
查看>>
设计工具产品是怎么收费的?
查看>>
我的友情链接
查看>>
如何在PDF阅读器中新建文档
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
Linkwedo 提升信息在决策中的力量
查看>>
雨林木风GhostXP_SP3装机版YN11.6_2011.06更新
查看>>
我的友情链接
查看>>
vim8.0 不能用鼠标
查看>>
OpenGL进阶(十) - obj文件的导入
查看>>
剑指XX游戏(八) - 腾讯2013校园招聘技术类笔试题详解
查看>>
docker 添加基础命令
查看>>