python全栈开发中级班全程笔记(第二模块、第三章)第3节:递归、内置函数

时间:2022-09-06 03:22:31

python全栈开发笔记第二模块

第三部分 :递归、内置函数

一、递归定义及使用

1、递归基础

定义:什么叫递归?递归就是在函数的执行中调用自己 

下面代码举例说明:

例:
def recursion(n):    #设置计数 
    print(n)         #为了能验证调用自己多少次,打印计数
    recursion(n+1)   #每次执行完加一
recursion(1)
执行代码结果:
1
2
3         #每执行一次就会+1,就像 for 循环(循环到边界)
....... 996 997 998raceback (most recent call last): RecursionError: maximum recursion depth exceeded while calling a Python object #发现报错,报错的意思是说递归到了最大  极限(系统默认1000次,除去上下被执行的2次,正好998次)

查看系统默认递归层:

例:
import sys #导入python工具箱 sys print(sys.getrecursionlimit()) #打印系统默认递归层
def recursion(n):                          #再次执行
    print(n)         
    recursion(n+1)  
recursion(1)
执行代码结果:

1000 #打印系统默认递归层是1000次
1
2
3                 #每执行一次就会+1,就像 for 循环(死循环到边界)
....... 
996
997
998raceback (most recent call last):
RecursionError: maximum recursion depth exceeded while calling a Python object

 修改系统默认递归层:

例:
import sys                            #导入python工具箱 sys
print(sys.getrecursionlimit())        #打印系统默认递归层
sys.setrecursionlimit(1500) #系统默认递归层修改方法(修改成1500)
def recursion(n):  
    print(n)        
    recursion(n+1)                    #再次执行
recursion(1)
执行代码结果:

1
2           
....... 
996
......
1497 #发现已经修改了设置递归层 (1500)
1498raceback (most recent call last):
RecursionError: maximum recursion depth exceeded while calling a Python object

为什么限制递归次数,因为函数在递归执行的过程中,

都是占用系统运行内存的(函数只有执行完才会释放内存,因为递归就是执行函数本身 ,所以,是执行不完的)

一旦达到内存极限,就会导致吧系统内存撑爆,所以限制了递归次数 

2、递归与栈的关系

在计算机中,函数的调用时通过栈来实现的。

栈 :是一个概念词,不是真实存在的,是一个数据结构。他就像一个弹弹匣,有一定的限制,

每执行一次函数,就会往栈内压缩一次,就像往弹匣内压一颗子弹一样,一旦达到限制就会导致栈溢出。就是太满,会撑爆内存

下面一张图了解栈

python全栈开发中级班全程笔记(第二模块、第三章)第3节:递归、内置函数

 

3、递归的作用(一)

  递归可以解决很多复杂的数学问题,在函数领域的作用就像 while 循环,

下面用代码举例说明:

#递归的作用 #递归可以解决很多复杂的数学问题,在函数领域的作用就像 while 循环,
#一个需求实现递归的作用
# 10 整除 2 直到 0  为止
def calc(n):

    v = int(n/2)       #设置公式
    print(v)
    if v == 0:         #增加判断
        return "OK"   #条件成立递归终止(return为递归的终止语句)

    calc(v)           #递归
    print(v)          #打印反向值

calc(10)              #传入参数

执行代码结果:

5
2
1
0      #整除 0 退出做到了,但是为什么会打印反向值呢?下一节解释
1
2
5

上一个题为什么会出现反向打印值,下面一张图揭晓

python全栈开发中级班全程笔记(第二模块、第三章)第3节:递归、内置函数

如图所示:

函数中,递归执行的中心点是在判断条件成立和 return 返回值的地方,

所以会形成以条件成立为中心向外辐射,先层层传进直到条件成立,再层层退出

形成  5  2  1   0中心点  1  2  5  这样的反射

***递归特性小结:

      • 每一个正常的递归,都要有边界,都要有明确的判断条件,因为递归是无限制的,如果不设边界,会导致内存崩溃或者报错
      • 每次进入更深一层递归时,问题规模相比上一层递归,都要有所减少(每进入更深一层递归,问题规模的圈子就要更集中,更小)
      • 递归执行效率不高,慎用,递归层次过多会导致栈溢出

4、递归的作用(二)

递归的作用很多:求斐波那契数列、汉诺塔、多级评论树(这几个数据结构比较复杂,以后学的深入会讲)、二分查找、求阶乘等等。

求阶乘 任何大于1的自然数 n 阶乘方法公式:n! = 1 * 2 * 3 * 4 *......* n 或 n! = n * (n-1)! 例:4!= 4 * 3 * 2 * 1 = 24 就是说,4 的阶乘就等于 3 阶乘的和再乘以 4 以此类推(总体意思就是说先要把最小的阶乘算出来,依次往大乘)
下面代码验证下:
def factorial(n):

    if n == 1:                    #加判断,否则会报错
        return 1
    return n * factorial(n-1)    # n! = n * (n-1)!

print(factorial(10))
执行代码结果:
3628800

5、尾递归优化

递归执行效率低,会导致栈溢出,解决这个办法的方式就是尾递归优化。

函数的递归效率低是因为在函数每执行一层,就会把数据存进栈,等下一层调用,

优化的代码格式:

例:
def calc(n):
    
    print(n)
    return calc(n+1)    #如果这样写代码,直接返回上一层的结果,这层的执行就会与上一层没关系,
#这样,上一层就不会被调用,可以释放空间,只要保存当前层的数据即可
calc(1) #求阶乘,不属于尾递归优化,因为他的一些数据是活的,必须是上一层计算结果

注意:尾递归优化,不是所有语言都支持, c 语言有优化,

在python语言里是没有直接作用的,因为python语言没有优化,它是一个技术概念,

JS 是有尾递归优化的,不存在效率低递归不是所有场景都用你管得到,但是我们要知道 

二、函数--内置方法

  1、基本内置函数:

    在python里,len(读取长度) 、str(字符串)、type(查看类型)、int(变成整数)

之所以能用这些,是因为调用了 python 里的内置函数,函数要调用需先定义,之所以这些不用定义,

是因为这些都是 python 里的内置函数(python 解释器系统定义好的),都有哪些呢?

python全栈开发中级班全程笔记(第二模块、第三章)第3节:递归、内置函数

下面一一对应作用:

abs()        绝对值,(负数也会以正数来表示)

dict()      把数据转成字典       

help()     内置帮助功能(如果语法不会,可以在 python 解释器中 help(要帮助的语法))

min()  返回数据中最小的值

>>> s = [1, 2, 80, 5, 11, -8]              
>>> min(s)                                 # min 一下 s
-8                                         #返回了最小的值

     max()     相反,返回数据中最大的值

   bool()     判断是否布尔类型(布尔,所有的数据类型都自带布尔值,只有在0 、 None 或者 list、dict、set、tuple为空的时候返回 False

      *a l l()      判断如果 bool()返回什么 all()就返回什么(除了空列表不同 bool 返回 False ,all 返回 True,只要有一个是错误的,都会返回 False

  *any()       判断 bool() 里面的每个值,只要有一个对的,就会返回 True ,(False和 0 都是错的)

  ***********************以上两个经常会用,判断数据集合内的真与假,请牢记*****************************

   dir()          打印当前程序中的所有变量名(包括 python 解释器自带变量)

     hex()         以 十六 进制显示数字 

     slice()      切片格式化

>>> l = list(range(10))                 #定义一个列表
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> s = slice(1,7)                        #定义切片范围
>>> l[s]                                      #应用
[1, 2, 3, 4, 5, 6]                           #返回切片值

   divmod()  写进去相除的2个值,会返回整除值 和 余数值 

>>> divmod(17,3)        #写进要相除的两个数
(5, 2)                  #返回整除值和余数

       id()           返回内存地址

   sorted()    排序,可自定义排序规则(默认从小到大,也可语法实现反转)

>>> t                                                   #设定字典变量
{0: -22, 1: -21, 2: -20, 3: -19, 4: -18, 5: -17, 6: -16, 7: -15, 8: 55, 9: -13, 10: -12,
11: -11, 12: -10, 13: -9, 14: -8, 15: -7, 16: -6, 17: -5, 18: 66, 19: -3} >>> sorted(t.items(),key=lambda x:x[1]) #通过语法实现默认排序(按照value排序,默认是 key 排序) [(0, -22), (1, -21), (2, -20), (3, -19), (4, -18), (5, -17), (6, -16), (7, -15), (9, -13), (10, -12),
(11, -11), (12, -10), (13, -9), (14, -8), (15, -7), (16, -6), (17, -5), (19, -3), (8, 55), (18, 66)] >>> sorted(t.items(),key=lambda x:x[1],reverse = True) #通过语法实现 value 反转排序 [(18, 66), (8, 55), (19, -3), (17, -5), (16, -6), (15, -7), (14, -8), (13, -9), (12, -10), (11, -11),
(10, -12), (9, -13), (7, -15), (6, -16), (5, -17), (4, -18), (3, -19), (2, -20), (1, -21), (0, -22)]

      ascii()   除了ASCII 码表内的字符正常显示,其他字符转成 unicode 编码格式的二进制

>>> s = "abs毅龍"
>>> ascii(s)
"'abs\\u6bc5\\u9f8d'"
   enumerate() 枚举,循环返回列表的索引值
  input() 获取用户输入
  oct() 返回整数的 8 进制格式
  bin() 返回整数的二进制格式
 eval() 按解释器规则把少量代码解析执行(处理单行代码)(能拿到返回值)
 exec() 把多行代码解析执行(处理多行代码)(拿不到返回值)
print(exec("1+2*5"))            #用exec 可以执行多行代码,但是拿不到返回值
print(eval("1+2*5"))            #用eval 可以执行少量代码,但是能拿到返回值
int() 将数字或字符串转换成整数
open() 打开文件
str() 转换字符串
ord() 返回字符在 ASCII 码表对应数字
chr() 返回数字在 ASCII 码表对应字
sum()
求和
>>> a
(1, 8, -4, 22, 58, 33, 5552, -5555, 444)
>>> sum(a)
559 
  bytearray() 不开辟内存地址修改字符串
s = "aasd,路飞"
s = s.encode('utf-8')      #先转换代码
s = bytearray(s)            
s[5] = 233
s[2] = 116                   #修改字符串
s[6]= 185
s = s.decode()             
print(s) 
  map() 执行传进去的函数计算公式和数值
print(list(map(lambda x:x*x, [1,4,5,2,6,8,7])))    # map 内传进去2个参数  
   filter() 过滤,拿出想要的值
print(list(filter(lambda x: x>3, [0.5,1,2,1,5,8,99,6,4,3]))) # filter 内传进去2个参数
   reduce () 可设置一个函数公式让两个参数相加或相乘
import functools                                              #需导入工具包
f = functools.reduce(lambda x,y:x+y,[1,2,5,8,7,4,])           #可以是2个数相乘(累乘)
f1 = functools.reduce(lambda x,y:x+y,[1,2,5,8,7,4,],77)       #可设置两个参数
print(f,f1)
pow() 返回值的次方
bytes() 字节类型
float() 浮点类型
print() 打印除了打印,打印完自动换行,有很多参数,
可以设置结尾去除默认换行(end=) 可以设置字符串间的连接(sep=) 还可直接把数据打印到文件内
1、(end=)
s = "hello \n my name is Guoyilong \n age 28 \n join lambda "
s1 = print(s,end="ss")

执行代码结果:
hello 
 my name is Guoyilong 
 age 28 
 join lambda s
2、 (sep=)
print("wages","names",sep="->")    #需传进去2个值 和 sep="连接"
执行代码结果:
wages->names 

 

(3) 直接把数据打印到本地文件
msg = "缺少奋斗的人,是没有理想的"
f = open("print_tofilee","w")              #在pycharm 内创建文件
print(msg,"缺少毅力的人,即使奋斗了也不会有结果",end="=======",sep="*******",file=f)     #把上面2个知识点也加进去
print(msg,"缺少毅力,奋斗不会有结果,没有坚持,但曾经拥有",end="=======",sep="*******",file=f)     #证明是否换行
执行代码结果:(打开文件内显示结果)
缺少奋斗的人,是没有理想的*******缺少毅力的人,即使奋斗了也不会有结果=======缺少奋斗的人,是没有理想的*******缺少毅力,奋斗不会有结果,没有坚持,但曾经拥有=======
   tuple() 转成元祖并把字符逐个分割
msg = "缺少奋斗的人是没有理想的"
print(tuple(msg))              #打印加了内置函数后的结果
执行代码结果:
('', '', '', '', '', '', '', '', '', '', '', ''
   callable() 判断变量是否可调用(主要测试函数)
msg = "缺少奋斗的人是没有理想的"
def clac():
    a = 5
    b = 7
    a + b
    return a,b
clac
print(callable(msg))          #判断普通变量
print(callable((clac)))      #判断函数变量(如果给了你一个变量,判断是否为函数的时候,可以用这样的方法解决)
执行代码结果:
False                #普通变量不可执行返错误
True                #函数代码可执行返回正确
format() 格式化方法
len() 返回参数的长度
type() 查看数据类型
frozenset() 不可变的集合
s = {1,77,4,52,6,5,8}
s.pop()               #随机删除1个值
print(s)              #已成功删除
s = frozenset(s)
print(s.pop())      
执行代码结果:

{4, 5, 6, 8, 77, 52} #第一个print可正常打印
  File "python学习第二模块\第三章\递归、内置函数.py", line 223, in <module>
    print(s.pop()) 
AttributeError: 'frozenset' object has no attribute 'pop' 
#报错提醒经过 frozenset() 函数处理的变量不可被修改
list() 转成列表
range() 返回给定整数的列表(默认从小到大)
for i in range(8):                  #给定8的意思就是 >= 0 , <8 print(i)
执行代码结果:
0
1
2
3
4
5
6
7
vars() 返回当前编译器所有变量与对应的值
locals() 函数内打印局部变量,函数外打印全局变量(包含局部变量)
f = "wages"
def calc():
    n = 72
    print(locals())
print(locals(),calc())
globals() 打印全局变量(不分函数内外)
repr() 以字符串形式返回对象
zip() 压缩(2合1)
a = [1,8,5]
b = ["ca","vv","re","bb"]          #设置2个不同长度的列表
c = dict(zip(a,b))
c1 = list(zip(a,b))                 #可以设置不同类型创建压缩的对应值
print(c,c1)                         #列表内多余的值会丢弃(删除没有对应的值)
执行代码结果:
{1: 'ca', 8: 'vv', 5: 're'} [(1, 'ca'), (8, 'vv'), (5, 're')]

reversed() 反转(默认反向排序

complex() 返回一个实数和一个虚数

round(1.555582,3 ) 设定浮点数的取值范围(2个参数,一个浮点数,一个要保留几位小数的值)

delattr(),hasattr(),getattr(),setattr() 面对对象四剑客,学对象时再说

hash("ssddde") 生成唯一的数字值

memoryview() 现在用不到(大数据拷贝的时候可以进行内存映射)

set() 转集合类型

n = (1,0,2,5,6,4,7,"wage","hello")           #设一个元祖
n2 = [1,0,5,8,6,3,"yes","world"]             #设一个列表
print(set(n))
print(set(n2))
执行代码结果:
{0, 1, 2, 4, 5, 6, 7, 'hello', 'wage'}       #元祖转成集合
{0, 1, 3, 'world', 5, 6, 8, 'yes'}           #列表转成集合
**函数基础作业:
        登录账号后修改个人信息:
choice = None
def info():
    _list = []
    with open("成员信息","r",encoding="gbk") as f:
        for i in f:
            i = i.strip().split(",")
            _list.append(i)
        return _list
_list = info()


def wafe(nm, age, job, phone, time):
    print("""-------- 个人信息 --------
1.姓名:%s
2.年龄:%s
3.职位:%s
4.电话:%s
5.入职时间:%s
-----------end-----------""" % (nm,age,job,phone,time))

def revise():
    for li in _list:
        if choice[0] == li[0]:
            _list.remove(li)
            _list.append(choice)
    with open("成员信息", "w", encoding="gbk") as f:
        for user in _list:
            f.write('%s\n' % (','.join(user)))

count = 0
while count < 3:
    name = input("user name:").strip()
    pas = input("pass word:").strip()
    for user in _list:
        if name == user[0] and pas == user[1]:
            choice = user
            print("""
--------------------welcome %s------------------------""" % name)
            while True:
                inp = input("""
选择功能:( b返回 q 退出)
       1、打印信息
       2、修改信息
       3、修改密码
>>>: """)
                if inp == "1":
                    wafe(user[2], user[3], user[4], user[5], user[6])
                    pass
                elif inp == "2":
                    while True:
                        print(user)
                        wafe(user[2], user[3], user[4], user[5], user[6])
                        inp2 = input("请输入要修改的编号:").strip()
                        if inp2 == "1":
                            print("当前名字:%s" % user[2])
                            ip1 = input("请输入新名字:").strip()
                            choice[2] = ip1
                            revise()
                        elif inp2 == "2":
                            print("当前年龄:%s" % user[3])
                            ip2 = input("请输入新的年龄:").strip()
                            choice[3] = ip2
                            revise()
                        elif inp2 == "3":
                            print("当前职位:%s" % user[4])
                            ip3 = input("请输入新职位:").strip()
                            choice[4] = ip3
                            revise()
                        elif inp2 == "4":
                            print("当前电话为:%s" % user[5])
                            ip4 = input("请输入新的电话:").strip()
                            choice[5] = ip4
                            revise()
                        elif inp2 == "5":
                            print("当前入职时间为:%s" % user[6])
                            ip5 = input("请输入新的入职时间:").strip()
                            choice[6] = ip5
                            revise()
                        elif inp2 == "b":
                            break
                    else:
                        print("没有当前选项!")

                elif inp == "3":
                    print("当前密码:%s" % user[1])
                    inp3 = input("请输入新密码:").strip()
                    choice[1] = inp3
                    revise()
                elif inp == "q":
                    exit()
                else:
                    print("没有当前选项")
    else:
        print("输入错误请重试!")
        count += 1
————————————————————————结束线————————————————————————————