马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 heidern0612 于 2018-12-17 09:59 编辑
写的内容都是自我思考的过程,难免有疏漏和错误的地方,欢迎广大鱼油给予指正!
1、global 和 nonlocal
global: 用于作用全局,相当于声明最外部的变量,global含义为全球的,这里理解为全局的。权限比较大,不轻易使用。
nonlocal: 只作用于内部函数修改外部函数,用于嵌套函数使用,出了函数并不好使。
简单举个老师的例子:
def outside():
var = 5
def inside():
print(var)
var = 3
inside()
outside()
输入结果显示var并没有被定义,因为内部函数先打印了var,但是内部函数里var并没有被定义。解决办法一是使用nonlocal,二是把var = 3跟print(var)换行。
老师举的几个例子应该都比较好理解,就不多说了。
2、如何访问funIn() ?def funOut():
def funIn():
print('宾果!你成功访问到我啦!')
return funIn
这里老师给的答案是funOut()(),我当时就蒙了一下,两个括号什么鬼?后来分析了一下,恍然大悟。
funOut()() = funOut()+() ,调用funOut()是什么结果呢?屏幕会返回funIn的值(为空), 所以实际上funOut() = funIn,funIn+() = funIn() ,结果就是打印内容了。
稍微有点绕,但是分析清楚后,就是个简单的傻瓜问题了。
3、闭包实例解析:
#如果在一个函数的内部定义了另一个函数,外部的我们叫他外函数,内部的我们叫他内函数。
闭包含义: 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。
但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。
详解:(以下内容部分摘自网络)
def outer( a ): # outer是外部函数 a和b都是外函数的临时变量
b = 10
def inner(): # inner是内函数
print(a+b) #在内函数中 用到了外函数的临时变量
return inner # 外函数的返回值是内函数的引用
# 在这里我们调用外函数传入参数5
demo = outer(5) #此时外函数两个临时变量 a是5 b是10 ,并创建了内函数,然后把内函数的引用返回存给了demo
# 外函数结束的时候发现内部函数将会用到自己的临时变量,这两个临时变量就不会释放,会绑定给这个内部函数
demo() # 返回值为15 # 我们调用内部函数,看一看内部函数是不是能使用外部函数的临时变量
# demo存了外函数的返回值,也就是inner函数的引用,这里相当于执行inner函数
demo2 = outer(7)
demo2() #返回值为17
外函数返回了内函数的引用:
当我们在python中定义一个函数def demo(): 的时候,内存当中会开辟一些空间,存下这个函数的代码、内部的局部变量等等。
这个demo只不过是一个变量名字,它里面存了这个函数所在位置的引用而已。
我们还可以进行x = demo, y = demo, 这样的操作就相当于,把demo里存的东西赋值给x和y,这样x 和y 都指向了demo函数所在的引用。
在这之后我们可以用x() 或者 y() 来调用我们自己创建的demo() ,调用的实际上根本就是一个函数,x、y和demo三个变量名存了同一个函数的引用。
对于闭包,在外函数outer中 最后return inner,我们在调用外函数 demo = outer() 的时候,outer返回了inner,inner是一个函数的引用,这个引用被存入了demo中。
所以接下来我们再进行demo() 的时候,相当于运行了inner函数。
同时我们发现,一个函数,如果函数名后紧跟一对括号,相当于现在我就要调用这个函数,如果不跟括号,相当于只是一个函数的名字,里面存了函数所在位置的引用。
外函数把临时变量绑定给内函数:
按照我们正常的认知,一个函数结束的时候,会把自己的临时变量都释放还给内存,之后变量都不存在了。
一般情况下,确实是这样的。但是闭包是一个特别的情况。
外部函数发现,自己的临时变量会在将来的内部函数中用到,自己在结束的时候,返回内函数的同时,会把外函数的临时变量送给内函数绑定在一起。
所以外函数已经结束了,调用内函数的时候仍然能够使用外函数的临时变量。
在我编写的实例中,我两次调用外部函数outer,分别传入的值是5和7。
内部函数只定义了一次,我们发现调用的时候,内部函数是能识别外函数的临时变量是不一样的。
python中一切都是对象,虽然函数我们只定义了一次,但是外函数在运行的时候,实际上是按照里面代码执行的。
外函数里创建了一个函数,我们每次调用外函数,它都创建一个内函数,虽然代码一样,但是却创建了不同的对象,并且把每次传入的临时变量数值绑定给内函数,再把内函数引用返回。
虽然内函数代码是一样的,但其实,我们每次调用外函数,都返回不同的实例对象的引用,他们的功能是一样的,但是它们实际上不是同一个函数对象。
使用闭包的过程中,一旦外函数被调用一次返回了内函数的引用,虽然每次调用内函数,是开启一个函数执行过后消亡,但是闭包变量实际上只有一份,每次开启内函数都在使用同一份闭包变量。#coding=gbk
def outer(x):
def inner(y):
nonlocal x
x+=y
return x
return inner
a = outer(10)
print(outer(10)(1)) #执行完释放掉
print(outer(10)(3)) #执行完释放掉
print(a (1)) #执行完被变量a绑定,未释放掉。
print(a (3)) #执行完被变量a绑定,未释放掉。
print(a (3)) #执行完被变量a绑定,未释放掉。
头两个print打印的结果是11和13,后三次打印的结果一次是11、14和17。由此可见,每次调用inner的时候,使用的闭包变量x实际上是同一个。
4、动动手1解析
统计字符串出现的次数,并找到小甲鱼老师留存的一句话。str1 = '''拷贝过来的字符串'''
list1 = []
for each in str1: #只要是找出现次数或者统计次数的,都离不开for循环
if each not in list1: #成员操作符 not in 。如果each遍历完str1之后不在列表list1里的话:
if each == '\n': #简单判断是否换行,是的话就统计换行符,不是的话统计其他的字符出现的次数。
print('\\n', str1.count(each))
else:
print(each, str1.count(each))
list1.append(each) #如果each不在list1里面,就添加到list1空列表里。
最后输出结果发现Good Luck (o出现两次,另外7个字母各出现1次)。
5、算密码的问题,我借用论坛一位"youxi"大神的解法,再加上我自己的解释:
原贴地址
题目要求是密码字符为小写,并且前后有且只有三个大写, 说明如果x是密码 :xABCxABCx
即 x前面必须有三个大写字母!。 如果x前面有第四个,第四个必须是小写。如果x后面有第四个,也必须是小写。 你一定要弄明白这个逻辑才能往下看。
首先,把字符串定义为str1 。设定countA,B,C 定义为前面大写,小写,以及后面大写。然后灵活运用字符串的内置函数进行判断。len(str1) 是判断字符串长度,根据字符串每个字符的索引值依次判断str1 = '''ABSaDKSbRIHcRHGcdDIF'''
countA = 0 # 统计前边的大写字母
countB = 0 # 统计小写字母
countC = 0 # 统计后边的大写字母
length = len(str1)
#解题思维是一个字符一个字符挨个依次判断:
for i in range(length):
if str1 == '\n':
continue
#如果字符是换行符,那么跳过继续。
if str1.isupper():
if countB: #如果字母是大写,并且小写出现过,x...A 情况。 如果字符是大写,首先判断if countB是否==0 如果不等于0 if语句继续执行 表示已经有小写字母x存在,那么countC += 1
countC += 1
else: #如果字母是大写,小写没出现过 , A...x 情况 。 如果countB 等于0 if语句不执行,执行下面 else语句 x前面大写字母数量+1
countC = 0
countA += 1
if str1.islower():
if countA != 3: #cABx...情况。如果本次判断是小写, 那么先判断前面3次是否都是大写 ifcountA !=3 表示 如果前面三次不是大写,那么不符合题目要求。 统计数据清零,重新统计
countA = 0
countB = 0
countC = 0
else:
if countB: #ABCdx...情况。如果前面三次都是大写,再判断if countB 是否等于0 如果不等于0 if语句执行 统计数据清空。
countA = 0
countB = 0
countC = 0
else:
countB = 1 #ABCxD...情况,如果 countB等于0. 表示前面有3个大写了,本次为小写,countB = 1 把本次小写的值赋值给target
countC = 0
target = i
if countA == 3 and countC == 3: ##如果前面三个都是大写,后面三个都是大写 。 根据程序逻辑已经排除了前面第四个是否大小写的情况,那么就判断后面第四个是否是大写!
if i+1 != length and str1[i+1].isupper(): #ABCxDEF 情况 判断D是否在字符串范围内情况,超出字符串范围清零,
#if i+1 != length and str1[i+1].isupper(): 既然要判断第四个, 那么首先就要判断i+1的值不超过length的值,如果超过了, 就表示i的索引值超过字符串的长度。
# 然后再判断第四个 str1[i+1].isupper()是否是大写。如果条件都成立 ,那么 统计数据清零。重新判断
countB = 0
countC = 0
else: #不超出的话,打印结果
print(str1[target], end='') #如果不成立 那么符合要求 打印target , 因为后面3个都是大写,第四个是小写,所以符合题目要求,因此 countA = 3
countA = 3
countB = 0
countC = 0
|