一、函数参数
1. 函数名及函数执行
先放结论:
函数名存放的是函数所在空间的地址;
函数名() 执行函数名所存放空间地址中的代码
函数名可以像普通的变量一样赋值
根据上面的结论 结合代码看:
def func01(): print("This is func01") # 1.执行func() func01() # This is func. #2. 打印函数名 print(func01) # <function func at 0x10d8491f0> #3. 函数名可以像普通的变量一样赋值 fun2 = func01 fun2() # This is func01
原理解析:
如下图,假设func01 这个函数名存放的地址是0x11, 0x11地址存放的内容是print的内容,执行func01()时,就是执行地址中的代码;又 函数名可以赋值, func2存放的地址就是func01的地址, 所以执行func2() 与func01()的结果是一样的。

2. 函数名 传参
如下, 函数名作为参数进行传递,因为函数名存放的是地址,实际就是地址的传递
def func01(): print("This is func01") # 函数名传参 def foo(func): func() foo(func01) # This is func01
原理解析:

二、闭包
1. 闭包的使用场景
当函数调用完, 函数内部定义的局部变量就会被销毁掉,但是我们有时候需要保存函数内的变量值, 比如在这个变量的基础上,进行其他的运算。怎么办呢? 就是使用闭包来解决这个问题。
2. 闭包的作用
闭包可以保存函数的变量, 不会随着函数调用完而销毁。
3. 闭包的定义

3. global关键字
前面说到在函数中修改全局变量,是不会成功的,因为Python的shadowing机制,会自动屏蔽,只会在函数内部创建一个跟全局变量名字一样的局部变量。
>>> count = 10
>>> def fun1(): count = 5 print('函数fun1()正在被调用') >>> count 10 >>>
为了在函数内部能够成功修改全部变量,使用global关键字,如下:
>>> count = 10 >>> def fun2(): global count ##使用global关键字 count = 5 print('函数fun2()正在被调用') >>> fun2() 函数fun2()正在被调用 >>> count 5 >>>
2.内嵌函数
内嵌函数中:内部函数fun2()的作用域(定义、调用)是在整个外部函数fun1()之内的
>>> def fun1(): ##外部函数 print('函数fun1()正在被调用') def fun2(): ##内部函数 print('函数fun2()正在被调用') fun2()
>>> fun1() 函数fun1()正在被调用 函数fun2()正在被调用 >>>
出了fun1()这个函数,就不可以对fun2()进行调用,Python最新版可以在外部函数之外调用内部函数
>>> def fun1(): print('函数fun1()正在被调用') def fun2(): print('函数fun2()正在被调用') fun2() >>> fun1() 函数fun1()正在被调用 函数fun2()正在被调用 >>> fun2() 函数fun2()正在被调用 >>>
3.闭包
①.定义:如果在一个内部函数里,对在外部作用域的变量的引用,则内部函数就叫做闭包。
>>> def funX(x): def funY(y): return x * y return funY >>> funX(8) <function funX.<locals>.funY at 0x0429DFA0>>>> i = funX(8) >>> type(i) <class 'function'> ## i 是个函数 >>> i(5) 40 >>> funX(8)(5) 40
在闭包中,外部不能调用(接上面的例子):
>>> funY(5) Traceback (most recent call last): File "<pyshell#41>", line 1, in <module> funY(5) NameError: name 'funY' is not defined >>>
2.内嵌函数中,内部函数不能修改非全局变量的外部变量,例如:
>>> def fun1(): x = 5 ##对于内部函数fun2()来说,x是非全局变量的外部变量 def fun2(): x *= x return x return fun2() >>> fun1() Traceback (most recent call last): File "<pyshell#50>", line 1, in <module> fun1() File "<pyshell#49>", line 6, in fun1 return fun2() File "<pyshell#49>", line 4, in fun2 x *= x UnboundLocalError: local variable 'x' referenced before assignment ##局部变量x在定义之前不能被使用 >>>
nonlocal关键字的使用
>>> def fun1(): x = 5 def fun2(): nonlocal x x *= x return x return fun2() >>> fun1() 25 >>>
作业
0.如果希望在函数中改变全局变量的值,应该使用什么关键字?
global
1.在嵌套的函数中,如果希望在内部函数修改外部函数的局部变量,应该使用什么关键字?
nonlocal
2.python的函数可以嵌套,但是要注意一下访问的作用域问题哦,请问一下代码存在什么问题?
def outside(): print('I am outside!') def inside(): print('I am inside!') inside()
解:访问的作用域问题,inside()是内嵌函数,其作用域(定义、调用)都只能在它的外部函数里面,外面或者别的函数体是不能调用inside()函数的,修改如下:
def outside(): print('I am outside!') def inside(): print('I am inside!') return inside() outside()
3.请问为什么代码A没有报错,但是代码B却报错了?如何修改?
#代码A def outside(): var = 5 def inside(): var = 3 print(var) inside() outside() #代码B def outside(): var = 5 def inside(): print(var) var = 3 inside() outside()
因为代码B中,local variable 'var' referenced before assignment,说的是变量var没有被定义就拿来使用,所以报错
outside()函数中有一个var,inside()函数中也有一个var,python为了保护变量的作用域,故将outside()的var变量屏蔽起来,因此此时是无法访问到外层的var变量的
把上述代码中的内嵌函数的var = 5(赋值语句)修改为var+=5,就会报错。因为内嵌函数里面是不能修改非全局变量的外部变量。
4.请问如何访问funIn()呢?
def funOut(): def funIn(): print('宾果!你成功访问到我啦!') return funIn()
直接访问funOut(),因为funOut()里返回的是funIn()函数(即外部函数有对内部函数的调用)
5.请问如何访问funIn()呢?
def funOut(): def funIn(): print('宾果!你成功访问到我啦!') return funIn #-----------------------------这里没有()
这里需要用funOut()()访问
6.以下是闭包的一个例子,请你目测会打印什么内容?
def funX(): x=5 def funY(): nonlocal x x+=1 return x return funY a=funX() print(a()) print(a()) print(a())
动动手:
0.统计下边这个长字符串中各个字符出现的次数并找到小甲鱼送给大家的一句话
str1 = '拷贝过来的字符串' list1=[] for each in str1: if each not in list1: if each == '\n' print('\\n',str1.count(each)) else: print(each,str1.count(each))
1.请用已经学过的知识编写程序,找出小甲鱼藏在下边这个长字符串中的密码,密码的埋藏点符合以下规律:
a)每位密码为单个小写字母
b)每个密码的左右两边均有且只有三个大写字母
str1='拷贝过来的字符串' countA=0 countB=0 countC=0 length=len(str1) for i in range(length): if str1[i]=='\n': cotinue if str1[i].isupper(): if countB==1: countC +=1 countA=0 else: countA+=1 continue if str1[i].islower() and countA==3: countB=1 countA=0 target=i continue if str1[i].islower() and countC==3: print(str1[target],edn='') countA = 0 countB = 0 countC = 0
2.定义一个斐波那契数的函数
def fibs(num): #斐波那契数列 list1=[0,1] for i in range(num-2):#num个斐波那契数 list1.append(list1[-2] + list1[-1]) return list1 print(fibs(10))
浙公网安备 33010602011771号