鱼C论坛

 找回密码
 立即注册
查看: 5122|回复: 28

[学习笔记] 【Pyhon 020讲心得体会】【7位算密码问题】

[复制链接]
发表于 2018-11-18 20:33:05 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 heidern0612 于 2018-12-17 09:59 编辑

写的内容都是自我思考的过程,难免有疏漏和错误的地方,欢迎广大鱼油给予指正!


1、global 和 nonlocal

global:        用于作用全局,相当于声明最外部的变量,global含义为全球的,这里理解为全局的。权限比较大,不轻易使用。

nonlocal: 只作用于内部函数修改外部函数,用于嵌套函数使用,出了函数并不好使。

简单举个老师的例子:


  1. def outside():
  2.     var = 5
  3.     def inside():
  4.         print(var)
  5.         var = 3
  6.         
  7.     inside()
  8. outside()
复制代码


输入结果显示var并没有被定义,因为内部函数先打印了var,但是内部函数里var并没有被定义。解决办法一是使用nonlocal,二是把var = 3跟print(var)换行。

老师举的几个例子应该都比较好理解,就不多说了。



2、如何访问funIn() ?

  1. def funOut():
  2.     def funIn():
  3.         print('宾果!你成功访问到我啦!')
  4.     return funIn
复制代码


这里老师给的答案是funOut()(),我当时就蒙了一下,两个括号什么鬼?后来分析了一下,恍然大悟。

funOut()() = funOut()+() ,调用funOut()是什么结果呢?屏幕会返回funIn的值(为空), 所以实际上funOut() = funIn,funIn+() = funIn() ,结果就是打印内容了。

稍微有点绕,但是分析清楚后,就是个简单的傻瓜问题了。



3、闭包实例解析:

        #如果在一个函数的内部定义了另一个函数,外部的我们叫他外函数,内部的我们叫他内函数。

闭包含义: 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。


一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。

但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。


详解:(以下内容部分摘自网络)

  1. def outer( a ):                                # outer是外部函数 a和b都是外函数的临时变量
  2.         b = 10
  3.         def inner():                         # inner是内函数       
  4.                 print(a+b)                #在内函数中 用到了外函数的临时变量
  5.         return inner                        # 外函数的返回值是内函数的引用

  6.                                                 # 在这里我们调用外函数传入参数5
  7. demo = outer(5)                        #此时外函数两个临时变量 a是5 b是10 ,并创建了内函数,然后把内函数的引用返回存给了demo
  8.                                                 # 外函数结束的时候发现内部函数将会用到自己的临时变量,这两个临时变量就不会释放,会绑定给这个内部函数


  9. demo()                         # 返回值为15                        # 我们调用内部函数,看一看内部函数是不是能使用外部函数的临时变量
  10.                                                                         # demo存了外函数的返回值,也就是inner函数的引用,这里相当于执行inner函数

  11. demo2 = outer(7)
  12. 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中一切都是对象,虽然函数我们只定义了一次,但是外函数在运行的时候,实际上是按照里面代码执行的。

外函数里创建了一个函数,我们每次调用外函数,它都创建一个内函数,虽然代码一样,但是却创建了不同的对象,并且把每次传入的临时变量数值绑定给内函数,再把内函数引用返回。

虽然内函数代码是一样的,但其实,我们每次调用外函数,都返回不同的实例对象的引用,他们的功能是一样的,但是它们实际上不是同一个函数对象。


使用闭包的过程中,一旦外函数被调用一次返回了内函数的引用,虽然每次调用内函数,是开启一个函数执行过后消亡,但是闭包变量实际上只有一份,每次开启内函数都在使用同一份闭包变量。

  1. #coding=gbk
  2. def outer(x):
  3.     def inner(y):
  4.         nonlocal x
  5.         x+=y
  6.         return x
  7.     return inner

  8. a = outer(10)
  9. print(outer(10)(1))                #执行完释放掉
  10. print(outer(10)(3))                #执行完释放掉
  11. print(a (1))                         #执行完被变量a绑定,未释放掉。
  12. print(a (3))                         #执行完被变量a绑定,未释放掉。
  13. print(a (3))                         #执行完被变量a绑定,未释放掉。
复制代码


头两个print打印的结果是11和13,后三次打印的结果一次是11、14和17。由此可见,每次调用inner的时候,使用的闭包变量x实际上是同一个。



4、动动手1解析

统计字符串出现的次数,并找到小甲鱼老师留存的一句话。

  1. str1 = '''拷贝过来的字符串'''
  2. list1 = []

  3. for each in str1:                        #只要是找出现次数或者统计次数的,都离不开for循环
  4.     if each not in list1:                        #成员操作符 not in 。如果each遍历完str1之后不在列表list1里的话:
  5.         if each == '\n':                        #简单判断是否换行,是的话就统计换行符,不是的话统计其他的字符出现的次数。
  6.             print('\\n', str1.count(each))
  7.         else:
  8.             print(each, str1.count(each))
  9.         list1.append(each)                #如果each不在list1里面,就添加到list1空列表里。
复制代码


最后输出结果发现Good Luck (o出现两次,另外7个字母各出现1次)。



5、算密码的问题,我借用论坛一位"youxi"大神的解法,再加上我自己的解释:

原贴地址

题目要求是密码字符为小写,并且前后有且只有三个大写,  说明如果x是密码 :xABCxABCx
即 x前面必须有三个大写字母!。 如果x前面有第四个,第四个必须是小写。如果x后面有第四个,也必须是小写。  你一定要弄明白这个逻辑才能往下看。


首先,把字符串定义为str1  。设定countA,B,C 定义为前面大写,小写,以及后面大写。然后灵活运用字符串的内置函数进行判断。len(str1) 是判断字符串长度,根据字符串每个字符的索引值依次判断

  1. str1 = '''ABSaDKSbRIHcRHGcdDIF'''
  2. countA = 0  # 统计前边的大写字母
  3. countB = 0  # 统计小写字母
  4. countC = 0  # 统计后边的大写字母
  5. length = len(str1)

  6.                                 #解题思维是一个字符一个字符挨个依次判断:

  7. for i in range(length):
  8.     if str1 == '\n':
  9.         continue
  10.                                         #如果字符是换行符,那么跳过继续。
  11.   if str1.isupper():     
  12.         if countB:                        #如果字母是大写,并且小写出现过,x...A 情况。        如果字符是大写,首先判断if countB是否==0 如果不等于0 if语句继续执行 表示已经有小写字母x存在,那么countC += 1
  13.             countC += 1
  14.         else:                                #如果字母是大写,小写没出现过 , A...x 情况 。             如果countB 等于0  if语句不执行,执行下面 else语句 x前面大写字母数量+1
  15.             countC = 0
  16.             countA += 1
  17.                                        
  18.                                                                
  19.     if str1.islower():
  20.         if countA != 3:                #cABx...情况。如果本次判断是小写, 那么先判断前面3次是否都是大写 ifcountA !=3 表示 如果前面三次不是大写,那么不符合题目要求。 统计数据清零,重新统计
  21.             countA = 0
  22.             countB = 0
  23.             countC = 0
  24.         else:
  25.             if countB:                #ABCdx...情况。如果前面三次都是大写,再判断if countB 是否等于0 如果不等于0  if语句执行 统计数据清空。
  26.                 countA = 0
  27.                 countB = 0
  28.                 countC = 0
  29.             else:
  30.                 countB = 1                #ABCxD...情况,如果 countB等于0. 表示前面有3个大写了,本次为小写,countB = 1 把本次小写的值赋值给target
  31.                 countC = 0
  32.                 target = i



  33.    if countA == 3 and countC == 3:                ##如果前面三个都是大写,后面三个都是大写 。 根据程序逻辑已经排除了前面第四个是否大小写的情况,那么就判断后面第四个是否是大写!
  34.         if i+1 != length and str1[i+1].isupper():        #ABCxDEF  情况   判断D是否在字符串范围内情况,超出字符串范围清零,
  35.                                                                 #if i+1 != length and str1[i+1].isupper():  既然要判断第四个, 那么首先就要判断i+1的值不超过length的值,如果超过了, 就表示i的索引值超过字符串的长度。
  36.                                                                 # 然后再判断第四个 str1[i+1].isupper()是否是大写。如果条件都成立 ,那么 统计数据清零。重新判断
  37.             countB = 0                                               
  38.             countC = 0
  39.         else:                                                                #不超出的话,打印结果
  40.             print(str1[target], end='')                                #如果不成立  那么符合要求 打印target , 因为后面3个都是大写,第四个是小写,所以符合题目要求,因此 countA = 3
  41.             countA = 3
  42.             countB = 0
  43.             countC = 0
复制代码




评分

参与人数 2荣誉 +5 鱼币 +7 贡献 +3 收起 理由
YiMingC + 5 + 5 + 3 感谢分享!
亚里是多德 + 2

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-12-1 16:35:58 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-12-10 20:31:41 | 显示全部楼层
手题
第二问list1 = []
str = ''拷贝字符串“
length = len(str)
for i in range(0,length - 6):
    if(str[i+1].isupper() and str[i+2].isupper() and  str[i+3].islower() and str[i+4].isupper() and str[i+5].isupper() and str[i+6].isupper()):
        list1.append(str[i+3])
print(list1)
你好,能帮我解答一下吗,请问这样为什么错误了??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-10 20:35:27 | 显示全部楼层
手题
第二问list1 = []
str = ''拷贝字符串“
length = len(str)
for i in range(0,length - 6):
    if(str[i+1].isupper() and str[i+2].isupper() and  str[i+3].islower() and str[i+4].isupper() and str[i+5].isupper() and str[i+6].isupper()):
        list1.append(str[i+3])
print(list1)
你好,能帮我解答一下吗,请问这样为什么错误了??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-12-11 07:55:11 | 显示全部楼层
qinsmy 发表于 2018-12-10 20:35
手题
第二问list1 = []
str = ''拷贝字符串“

1、你没有考虑当前i位是大写还是小写,也没有考虑后面字符串后面那一位的大小写。

2、你判断的范围不对,应该是前三,后三大写,中间第四位小写,总共7位字符串。

3、你的and条件太多了,不要这么写。分开判断不好么?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2018-12-11 21:37:13 | 显示全部楼层
heidern0612 发表于 2018-12-11 07:55
1、你没有考虑当前i位是大写还是小写,也没有考虑后面字符串后面那一位的大小写。

2、你判断的范围不 ...

str = ‘"复制字符串''’
list1 = []
length = len(str)
for i in range(0,length - 6):
    if(str[i+0].isupper() and str[i+1].isupper() and  str[i+2].isupper() ):
        if( str[i + 3].islower() ):
            if(str[i + 4].isupper() and str[i + 5].isupper() and str[i + 6].isupper()):
               list1.append(str[i+3])
print(list1)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-11 21:37:55 | 显示全部楼层
qinsmy 发表于 2018-12-11 21:37
str = ‘"复制字符串''’
list1 = []
length = len(str)

str = ‘"复制字符串''’
list1 = []
length = len(str)
for i in range(0,length - 6):
    if(str[i+0].isupper() and str[i+1].isupper() and  str[i+2].isupper() ):
        if( str[i + 3].islower() ):
            if(str[i + 4].isupper() and str[i + 5].isupper() and str[i + 6].isupper()):
               list1.append(str[i+3])
print(list1)
这样写还出错了,难受
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-12-12 08:04:14 | 显示全部楼层
qinsmy 发表于 2018-12-11 21:37
str = ‘"复制字符串''’
list1 = []
length = len(str)

还是我说的那个问题,你没考虑字符串前后的大小写。

举个例子:ABBBxBBB或BBBxBBBA,这种情况。

不过当前已经可以判断前三和后三以及中间密码大小写的情况了,就差一点。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2018-12-12 19:36:23 | 显示全部楼层
谢谢你
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-12 20:42:43 | 显示全部楼层
本帖最后由 亚里是多德 于 2018-12-13 00:12 编辑

已编辑,问题想明白了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-1-3 20:01:12 | 显示全部楼层
for i in range(length):
    if str1 == '\n':
        continue
                                        #如果字符是换行符,那么跳过继续。

您好!
我想问for i in range (length)  #length不是一个数字吗,那么遍历的不都是数字吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-1-3 20:06:49 | 显示全部楼层
734820479 发表于 2019-1-3 20:01
for i in range(length):
    if str1 == '\n':
        continue


length是个数字,for i in range(lengh),就变成了遍历的次数了。

比如说
  1. for i in range (10):
  2.     print("我会运行10次")
复制代码


代码中print的内容就运行了10次。

这就是简单的次数和print结合。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2019-3-8 22:04:09 | 显示全部楼层
  1. if countA == 3 and countC == 3:                ##如果前面三个都是大写,后面三个都是大写 。 根据程序逻辑已经排除了前面第四个是否大小写的情况,那么就判断后面第四个是否是大写!
  2.         if i+1 != length and str1[i+1].isupper():        #ABCxDEF  情况   判断D是否在字符串范围内情况,超出字符串范围清零,
  3.                                                                 #if i+1 != length and str1[i+1].isupper():  既然要判断第四个, 那么首先就要判断i+1的值不超过length的值,如果超过了, 就表示i的索引值超过字符串的长度。
  4.                                                                 # 然后再判断第四个 str1[i+1].isupper()是否是大写。如果条件都成立 ,那么 统计数据清零。重新判断
  5.             countB = 0                                                
  6.             countC = 0
  7.         else:                                                                #不超出的话,打印结果
  8.             print(str1[target], end='')                                #如果不成立  那么符合要求 打印target , 因为后面3个都是大写,第四个是小写,所以符合题目要求,因此 countA = 3
  9.             countA = 3
  10.             countB = 0
  11.             countC = 0
复制代码

实在是太菜了,这一段还是看不懂....
您注释上说
如果countA = 3,countB = 3,那么根据程序逻辑已经排除了前面第四个是否大小写的情况,那么就判断后面第四个是否是大写!前面第4个被排除,我的理解是前面第四个是小写的密码,在countB中,那为什么要再判断后面第4位呢?

还有如果是ABCxDEF的情况,因此要判断D是否在字符串范围内的情况,超出字符串范围清零。为啥要判断D是否在字符串范围内呢?

最后为啥for i in range(length),即使他是遍历的次数,但并没有range到str1这个对象啊?为啥可以再str1中遍历了呢?

啊,我已经学的够慢了,还是难以开窍啊,逻辑都是一团浆糊....

麻烦大神解答了...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-9 08:38:42 | 显示全部楼层
来论坛学潮汕话 发表于 2019-3-8 22:04
实在是太菜了,这一段还是看不懂....
您注释上说
如果countA = 3,countB = 3,那么根据程序逻辑已经排 ...

1、如果countA = 3,countB = 3,那么根据程序逻辑已经排除了前面第四个是否大小写的情况,那么就判断后面第四个是否是大写!

这里判断的是前四个符合密码情况,也就是aAAA这种符合密码的情况,然后再判断后面是否符合密码的规律。如果不进行这个判断,就会出现aAAAA…这种情况。

2、假如测试密码的最后一位是小写或大写,下标已经是最后一位了,再+1的情况不是就超出密码的范围了吗?

3、没有range str1,因为range的str1都是字母,是用次数判断,而不是用字母判断。

比如说我需要判断“我是一个好人”这句话,我需要判断六次这个内容每个字符是不是一个汉字,这次六次就是length的长度了。



这道题其实对新人很不友好,如果不太了解,可以先跳过去,等后面学通了后再返回来看,不要硬钻牛角尖。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-9 10:43:11 | 显示全部楼层
heidern0612 发表于 2019-3-9 08:38
1、如果countA = 3,countB = 3,那么根据程序逻辑已经排除了前面第四个是否大小写的情况,那么就判断后面 ...

明白了,不钻这牛角尖了,谢谢您的耐心解答
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-4-2 11:14:03 | 显示全部楼层
最后一题我没有看懂,所以复制了代码运行了一下。有两处缩进错误,并且代码运行输出了空行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-4-6 11:11:05 | 显示全部楼层
ccluo 发表于 2019-4-2 11:14
最后一题我没有看懂,所以复制了代码运行了一下。有两处缩进错误,并且代码运行输出了空行
  1. class Find_Pass(object):
  2.     def __init__(self, string):
  3.         self.string = string

  4.     def method(self):
  5.         for i in range(len(self.string)):
  6.             if self.string[i].islower() and i >3 and i < (len(self.string)-4):
  7.                 if self.string[i-3:i].isupper() and not self.string[i-4].isupper()and \
  8.                         self.string[i + 1: i+ 4].isupper() and not self.string[i + 4].isupper() \
  9.                         and '\n' not in self.string[i-3:i+4]:
  10.                         print(self.string[i],end='')




  11. with open('.\string2\string2.txt',mode='r') as f:
  12.     mes = f.read()
  13.     str1 = mes
  14. demo = Find_Pass(mes)
  15. demo.method()
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-4-6 11:11:54 | 显示全部楼层
  1. class Find_Pass(object):
  2.     def __init__(self, string):
  3.         self.string = string

  4.     def method(self):
  5.         for i in range(len(self.string)):
  6.             if self.string[i].islower() and i >3 and i < (len(self.string)-4):
  7.                 if self.string[i-3:i].isupper() and not self.string[i-4].isupper()and \
  8.                         self.string[i + 1: i+ 4].isupper() and not self.string[i + 4].isupper() \
  9.                         and '\n' not in self.string[i-3:i+4]:
  10.                         print(self.string[i],end='')




  11. with open('.\string2\string2.txt',mode='r') as f:
  12.     mes = f.read()
  13.     str1 = mes
  14. demo = Find_Pass(mes)
  15. demo.method()
复制代码


我写的,简单明了,多了几个and,小甲鱼这种多逻辑的判断,感觉我初学者还是不适应。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-5-24 18:45:07 | 显示全部楼层
正学到这里,mark
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-11 09:23:17 | 显示全部楼层
请问 if countB是什么意思?还可以这样写吗?是不是类似于While True这样的?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-29 06:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表