Python其实很简单第十二章函数与变量的作用域
在前面已经多次提到函数这个概念,之所以没有解释什么是函数,是因为程序中的函数和数学中的函数差不多,如input()、range()等都是函数,这些都是Python的标准函数,直接使用就可以了。根据需要,用户也可以自定义函数。
12.1 函数
函数的结构:
def 函数名(参数):
函数体
return 返回值
例如:数学中的函数f(x)=2x+5在Python中可以定义如下:
def f(x):
y=2*x+5
return(y)
如果x取值为3,可以使用如下语句调用函数:
f(3)
下面给出完整的程序代码:
def f(x):
y=2*x+5
return(y)
res=f(3)
print(res)
运行结果:11
如上例中的x是函数f(x)的参数,有时也被称为形式参数(简称形参),在函数被调用时,x被具体的值3替换y就是函数的返回值,这个值3也被称为实际参数(简称实参)。
上例中的y是函数f(x)的返回值。并不是所有的函数都有参数和返回值。如下面的函数:
def func():
print("此为无参数传递、无返回值的函数")
func()
输出结果:此为无参数传递、无返回值的函数
可以看出,该函数func()无参数,故调用时不用赋给参数值。
函数也可以有多个参数,如f(x,y)=x²+y²,可用Python语言定义如下:
def f(x,y):
z=x**2+y**2
return z
print(f(2,3)) #调用函数f(x,y)
输出结果:13
也可以通过直接给参数列表中的参数赋值的方法,为参数添加默认值,如果用户赋予参数值,则按照用户赋值执行,否则使用默认值。例如:
def f(x,y=3):
z=x**2+y**2
return z
若调用时参数列表为(2,1),即x赋值为2,y赋值为1:
print(f(2,1))
输出结果为:5
若调用时参数列表为(2),即x赋值为2,y赋值省缺,则y使用默认值:
print(f(2))
输出结果为:13
回调函数,又称函数回调,是将函数作为另一函数的参数。
例如:
def func(fun,m,n):
fun(m,n)
def f_add(m,n):
print("m+n=",m+n)
def f_mult(m,n):
print("m*n=",m*n)
func(f_add,2,3)
func(f_mult,2,3)
输出结果:
m+n= 5
m*n= 6
在f_add(m,n)和f_mult(m,n)被定义前,func(fun,m,n)中的fun(m,n)就已经调用了这两个函数,即"先调用后定义",这也是回调函数的特点。
如果无法预知参数的个数,可以在参数前面加上*号,这种参数实际上对应元组类型。譬如,参会的人数事先不能确定,只能根据与会人员名单输入:
def func(*names):
print("今天与会人员有:")
for name in names:
print(name)
func("张小兵","陈晓梅","李大海","王长江")
运行后,输出结果为:
今天与会人员有:
张小兵
陈晓梅
李大海
王长江
参数为字典类型,需要在参数前面加上**号。
def func(**kwargs):
for i in kwargs:
print(i,kwargs[i])
func(a="a1",b="b1",c="c1")
输出结果为:
a a1
b b1
c c1
一个有趣的实例:
def func(x,y,z,*args,**kwargs):
print(x,y,z)
print(args)
print(kwargs)
func("a","b","c","Python","is easy",py="python",j="java",ph="php")
输出结果:
a b c # 前三个实参赋给前三个形参
("Python", "is easy") # *args接收元组数据
{"py": "python", "j": "java", "ph": "php"} # **kwargs接收字典数据
12.2 变量的作用域
变量的作用域即变量的有效范围,可分为全局变量和局部变量。
局部变量
在函数中定义的变量就是局部变量,局部变量的作用域仅限于函数内部使用。
全局变量
在主程序中定义的变量就是全局变量,但在函数中用关键字global修饰的变量也可以当做全局变量来使用。
全局变量的作用域是整个程序,也就是说,全局变量可以在整个程序中可以访问。
下面通过实例去讨论:
程序1:
a=1 # a为全局变量
def a_add():
print("a的初值:",a) # 在函数中读取a的值
a_add() # 调用函数a_add()
a+=1 # 主程序语句,a增加1
print("a现在的值是:",a) # 主程序语句,读取a的值
运行结果:
a的初值: 1
a现在的值是: 2
这个结果和我们想象的一样,全局变量a既可以在主程序中读取,也可以在子程序(函数)中读取。
程序2:
a=1
def a_add():
a+=1
print("a的初值:",a)
a_add()
print("a现在的值是:",a)
运行程序1时出现如下错误提示:
UnboundLocalError: local variable "a" referenced before assignment
意思是:局部变量"a"在赋值之前被引用。
从语法上来讲,该程序没有错误。首先定义了一个全局变量a并赋值为1,又定义了一个函数a_add(),函数内的语句a+=1就是出错的根源,虽然我们的初衷是想让全局变量a的值增加1,但从错误提示看,这个语句中的a并不是全局变量,而是局部变量。看来,在函数中读取全局变量的值是没有问题的(在程序1中已经得到了验证),但要在函数中改变全局变量的值是不行的(在程序2的错误提示a+=1中的a 是局部变量,而非全局变量)。
怎样解决这个问题?
程序3:
a=1
def a_add(x):
x+=1
return x
print("a的初值:",a)
a=a_add(a)
print("a现在的值是:",a)
运行结果:
a的初值: 1
a现在的值是: 2
结果的确是正确的,但在函数a_add(x)中没有调用变量a(没有出现变量a)。
程序4:
a=1
def a_add(a):
a+=1
return a
print("a的初值:",a)
a=a_add(a)
print("a现在的值是:",a)
运行结果:
a的初值: 1
a现在的值是: 2
对比程序4和程序3不难发现,其实程序4只是简单的把函数的参数x变成了a,这个a的实质和程序3中的x还是一样的。这进一步证实,函数中的a是局部变量,与主程序的全局变量a有着本质的区别。
程序5:
a=1
def a_add():
global a
a+=1
print("a的初值:",a)
a_add()
print("a现在的值是:",a)
运行结果:
a的初值: 1
a现在的值是: 2
程序5和程序2相比较,仅仅是在函数中添加了一个定义"global a",此时的局部变量a就可以当做全局变量使用,由于它和全局变量a同名,自然也就不用区分a究竟是全局变量还是局部变量了,在主程序和该函数内都可以访问、修改变量a的值了。
虽然使用global可使变量使用起来非常方便,但也容易引起混淆,故在使用过程中还是谨慎为好。
12.3 函数的递归与嵌套
递归,就是函数调用它自身。递归必须设置停止条件,否则函数将无法终止,形成死循环。
以计算阶乘为例:
def func(n):
if n==1:
return 1
else:
return n*func(n-1) #func( )调用func( )
print(func(5))
运行结果为:120
嵌套,指在函数中调用另外的函数。这是程序中常见的一种结构,在此不再赘述。
匿名函数
Python中可以在参数前加上关键字lambda定义一个匿名函数,这样的函数一般都属于"一次性"的。
例如:
程序1:这是一个常规的函数定义和调用。
def f_add(x,y):
return x+y
print(f_add(2,3))
输出结果:5
程序2:使用lambda定义匿名函数。
f_add=lambda x,y:x+y
print(f_add(2,3))
输出结果:5
从上面的代码可以看出,使用lambda仅仅减少了一行代码。f_add=lambda x,y:x+y中的f_add不是变量名,而是函数名。程序1和程序2的print( )语句中的参数都是一样的——调用函数f_add( )。所以,匿名函数并没有太多的优点。
性价比最高的旗舰机骁龙8双主摄5000mAh仅3000出头,别不识货在各个手机品牌都在冲击高端的大背景下,旗舰手机涨价已经成为了必然,像华米OV荣耀五家的旗舰手机售价都不约而同的来到了5000元档,体验确实都很不错,但是高昂的售价让人望而却步。对比
五款值得入手的大底拍照手机哪一款更具有性价比?随着手机拍照性能不断提升,大家用手机拍照也已经成为一种习惯,这也让单反和微单厂家最近这几年销量不断下滑。没有办法,微单生产厂家只好通过不断提高产品价格来获得更高的利润,所以这两年微
助听器可以找人代购吗?您好。助听器可以找人代购吗?不可以的。助听器是国家二类资料器械,需要经过专业的验配中心进行听力全面检测之后进行验配。找人代购的助听器,功率以及调试都不精确,患者的听力情况不一定适合
TCL电视好用吗?TCL电视最大的害处就是寿命太长。我前几年网购了一台该品牌的曲屏55英寸的电视,现在新居38平方米的客厅,它放在客厅很落魄,显得太小。我希望它坏掉,早一天换成85以上英寸,于是故意
戴助听器会被他人认为不正常吗?戴助听器和戴近视眼镜一样,都是借用外部器械来帮助我们听得和看得更清楚,都是正常的。只不过助听器还没有像眼镜那么普及,很多人对这方面还不了解,心里还有抵触和排斥,实际上耳朵有听力损失
微信公众平台将显示用户IP属地,你准备好了吗据了解,微信公众平台将显示用户的IP属地啦。国内用户将显示到省份地区,国外用户显示到国家,并且该功能为强制开启,用户无法主动关闭。微信是最常使用的社交软件,大家日常的社交和工作都离
浅谈巴菲特抨击比特币,比特币是否真正有价值?大奇讲故事存在就是合理。随着乌俄战争愈演愈烈,比特币区块链支付系统,又重新进入全球视野。其中俄国迅速把比特币作为国际结算支付工具,将彻底避开了以米国为首的西方国家所对俄罗斯全方位金
荣耀20为什么卖那么贵?荣耀20是华为公司手机子品牌荣耀在2019年5月发布的新品手机,荣耀成立以来一直是走线上性价比的路线,其推出的产品也获得了很多用户的喜爱。荣耀20系列有两个版本,荣耀20和荣耀20
华为Mate50Pro即将上线,一体沉浸式屏幕加持,5G实现新渠道如今的华为的确很无奈,在4纳米新机爆发的时代,华为只能按兵不动,大力维持现有的手机市场。毕竟芯片是智能手机的核心配件,目前国产厂商还无法自主生产4纳米芯片及5G相关元器件,只能依靠
观点李彦宏无人驾驶肯定会出事,甚至死亡,概率比有人驾驶低文懂车帝原创常思玥懂车帝原创行业近日,一张百度创始人董事长兼CEO李彦宏的朋友圈截图被曝光,李彦宏表示无人驾驶肯定会出事,甚至会出死亡事故,只是这个概率比有人驾驶低多了。百度创始人
摩托罗拉edgeX30三主摄旗舰手机骁龙8Gen1处理器,直降600元消费者普遍认为,手机中堆叠的配置越多,解锁的新技能就越多。这没有毛病,但是某些善用商机的商家会抓住消费者这一心理特征,在手机上大做文章。摄像头属于手机中的一项重要的配置,很多人都会