第020讲:函数 内嵌函数和闭包(课后测试题及答案 )

1.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))
        

猜你喜欢

转载自www.cnblogs.com/ananmy/p/12296545.html