【Python020--内嵌函数和闭包】

一、内嵌函数&闭包

1、最好是访问全局变量而不是修改全局变量,修改全局变量Python会内部屏蔽(修改后,函数会内部创建一个和全局变量一抹一样的变量)

>>> count = 5
>>> def MyFun():
    count = 10
    print(10)
 
>>> MyFun()
10
>>> print(count)
5
>>>

---外部先定义了一个count的全局变量,然后MyFun()内部对count进行了修改,打印MyFun()函数发现,是修改后的count,但是在打印count变量,仍然是全局变量的值5,这说明函数内对全局变量的修改,会直接被屏蔽

2、global关键字(可以用global关键字进行修改)

>>> count =5
>>> def MyFun():
    global count
    count = 10
    print(10)

>>> MyFun()
10
>>> print(count)
10
>>>

3、内嵌函数(内部函数):函数内部创建另外一个函数

>>> def fun1():
    print('fun1正在被调用!')
    def fun2():
        print('fun2正在被调用!')
    fun2()
   
>>> fun1()
fun1正在被调用!
fun2正在被调用!

4、闭包:

 def FunX(x):
    def FunY(y):
        return x*y
    return FunY

>>> FunX(8)(5)
40
>>> i = FunX(8)
>>> i
<function FunX.<locals>.FunY at 0x10598b400>
>>> i(5)
40

---闭包满足的两个条件:a、首先FunY是FunX的内部函数,并且FunY引用FunX的整个作用域  b、FunY引用FunX的变量x

---闭包的基本形式:

  在函数FunX中,定义FunY,FunY只能引用FunX定义的变量,之后FunX函数返回FunY函数的名字

>>> def fun1():
    x = 5
    def fun2():
        x *=x
        return x
    return fun2()

>>> fun1()
Traceback (most recent call last):
  File "<pyshell#75>", line 1, in <module>
    fun1()
  File "<pyshell#74>", line 6, in fun1
    return fun2()
  File "<pyshell#74>", line 4, in fun2
    x *=x
UnboundLocalError: local variable 'x' referenced before assignment
>>>

---报错的原因:(UnboundLocalError: local variable 'x' referenced before assignment)UnboundLocalError:赋值之前引用的局部变量'x',即:x是个局部变量,fun2赋值的时候x已经被屏蔽了,所以没办法引用

---解决方式:

A、采用数组这样的容器

>>> def fun1():
    x = [5]
    def fun2():
        x[0] *=x[0]
        return x[0]
    return fun2()

>>> fun1()
25

B、采用nonlocal关键字,强制声明x不是一个局部变量

>>> def fun1():
    x = 5
    def fun2():
        nonlocal x
        x *=x
        return x
    return fun2()

>>> fun1()
25

二、练习题

1、闭包举例:

def fun1():
    x = 5
    def fun2():
        nonlocal x
        x +=1
        return x
    return fun2
a = fun1()
print(a())
print(a())
print(a())

'''执行结果:
6
7
8 '''

 2、统计下边这个字符串中各个字符出现的次数并找到尘封送给大家的一句话

str1 = 'aabbc'
list1 = []   #建立空列表的目的:为了后面的if each not in list1:判断去重

for each in str1:

    if each not in list1: #目的:把str1中的字符添加到list1中,避免重复比较,
        if each == ' ':
            print ('\n',str1.count(each)) #str1.count(each)  计算str1数组里面each的个数
        else:
            print(each,str1.count(each))

        list1.append(each)

'''执行结果:
a 2
b 2
c 1
'''

'''对比没有list1[]和if each not in list1,来体现去重 '''

print('=======')

str2 = 'aabbc'

for each in str1:
    if each == ' ':
        print('\n',str2.count(each))
    else:
        print(each,str2.count(each))

'''执行结果:
a 2
a 2
b 2
b 2
c 1
'''

#对比的结果:前后两个执行结果可以得知:引入list1[]空列表以及后续的判断,目的都是为了统计的去重操作

3、请用已学过的知识编写程序,找出小甲鱼藏在下边这个长字符串中的密码,密码的埋藏点符合以下规律:

a)、每位密码为单个小写字母

b)、每位密码的左右两边有且只有三个大写字每

def findSecret(str1):

countA = 0 #统计前面的大写字母
countB = 0 #统计前面的小写字母
countC = 0 #统计后面的大写字母
length = len(str1)

for i in range(length):
if str1[i] == ' ':
continue

if str1[i].isupper(): #如果str1[i]是大写字母
if countB: #如果已经出现了小写字母
countC +=1 #统计后边的大写字母
else: #如果未出现小写字母
countC = 0 #清空后面的大写字母
countA +=1 #统计前面的大写字母


if str1[i].islower(): #如果str1[1]是小写字母
if countA != 3: #如果前面不是三个大写字母
countA = 0 #清空记录,重新统计
countB = 0
countC = 0
else: #如果前面是三个大写字母(满足条件)
if countB: #如果已经存在小写字母
countA = 0 #清空记录,重新统计
countB = 0
countC = 0
else: #如果只有一个小写字母
countB = 1 #标记一下countB
target = i #定位目标


if countA == 3 and countC ==3: #如果前后都是三个大写字母
if i+1 != length and str1[i+1].isupper():#如果第四个也是大写字母(不满足条件)
countB = 0 #清空记录B和C
countC = 0
else: #如果仅有三个大写字母(满足条件)
print(str1[target],end= '') #打印目标,结尾不换行
countA = 3
countB = 0 #清空记录B和C
countC = 0

return ''


str2 = '''dQmaKZSdqKNrnvJlcyVMKuNWmuoOeyKecgjXbmSqnpjwJEaDYoehEklEgJyiksGxdEKgfYRXQecRZgfe
AAAbCCC'''

print(findSecret(str2))




原文地址:https://www.cnblogs.com/frankruby/p/9143810.html