翼度科技»论坛 编程开发 python 查看内容

函数

9

主题

9

帖子

27

积分

新手上路

Rank: 1

积分
27
函数

一、函数的基本使用

1.函数简介

使用函数目的就是为了减少重复编写代码
循环:在相同的地方反复执行代码
函数:在不同的地方反复执行代码
没有函数:维修工每次工作的时候都要先创造工具再工作
有函数:维修工再工作的时候直接拿工具过来工作
2.函数的语法结构

定义阶段
  1. def 函数名(形参):
  2.         '''函数注释'''
  3.         函数体代码
  4.     return 返回值
复制代码
调用阶段
  1. 函数名(实参)
复制代码
1.def
​        定义函数的关键字
2.函数名
​        命名等同于变量名 要做到见名知意
3.形参
​        可以写 (单个或多个)也可以不写
​        主要用于接受外界传递给函数体代码内部的数据
​        可以理解为使用该函数的条件
4.函数体注释
​        类似于说明说 介绍函数的功能和使用方法
5.函数体代码
​        整个函数的核心 写逻辑代码的地方
6.return
​        使用完函数后有没有相应的反馈
3.函数的的定义与调用

函数名()执行优先级最高(定义阶段除外)

  • 函数必须先定义在调用
  • 函数在定义阶段只检测函数体代码的语法 不执行函数体代码
  • 函数在调用阶段才会执行函数体代码
  • 定义函数用def 调用函数用函数名()
4.函数的分类


  • 内置函数
    1. 解释器直接定义好的可以直接用的 eg:len()
    2. #数据类型的内置方法也是算内置函数 必须要用.的方式才能使用
    复制代码
  • 自定义函数

    • 空函数
      1. 函数体代码为空 用pass或...补全
      2. 空函数主要作为前期项目搭建
      3. def func():
      4.         pass
      复制代码
    • 无参函数
      1. 函数定义阶段括号内没有填写参数
      2. def func():
      3.         print('xxx')
      4. #无参函数直接函数名加括号调用即可使用
      复制代码
    • 有参函数
      1. 函数名定义阶段括号里写参数
      2. def func(a):
      3.     print(a)
      4.    
      5. func(123) #123
      6. #有参函数需要函数名加括号并传对应个数的实参才能调用
      复制代码

5.函数的返回值


  • 什么是返回值
    调用函数之后返回给调用者的结果 也可以理解为函数体代码执行完有没有反馈
  • 如何获取返回值
    变量名 = 函数名()
    1. def func():
    2.     a = 666
    3.     print(123)
    4.     return a
    5. res = func()
    6. print(res)
    7. #666 123
    8. '''
    9. 函数定义阶段 不执行函数体代码 看同一级别
    10. res=func() 函数名加括号调用 执行函数体代码
    11. a = 666 打印123 return 返回666 结束函数体代码 把结果绑定给res
    12. 打印res
    13. '''
    复制代码
  • 函数返回值的多种情况

    • 函数体代码中没有return关键字 :默认返回None
      1. def func():
      2.     pass
      3. res=func()
      4. print(res)
      5. #结果为:None
      复制代码
    • 函数体代码有return关键字:后面不写东西也返回None
      1. def func():
      2.     pass
      3.     return
      4. res=func()
      5. print(res)
      6. #结果为:None
      复制代码
    • 函数体代码有return关键字:后面有什么就返回什么(变量名就返回对应的数据值)
      1. def func():
      2.     pass
      3.     return 123  #如果是变量名则返回对应的值
      4. res=func()
      5. print(res)
      6. #结果为:123
      复制代码
    • 函数体代码有return关键字:后面多个数据之用逗号隔开 默认自动组织成元组返回 列表需要自己定义
      1. def func():
      2.     pass
      3.     return 1,2 #多个数据值用逗号隔开
      4. res=func()
      5. print(res)
      6. #结果为:(1,2)
      7. '''
      8. 列表字典需自己定义  return [1,2]
      9. 如果有一个没定义则外层用元组包起来([1,2],3)
      10. '''
      复制代码
    • 当函数体代码遇到return关键字会立刻结束函数体代码的运行(类似于break)
      1. def func():
      2.     print('上面')
      3.     return 'a'
      4.     print('下面') #永远不会执行
      5. func()
      6. #结果为:上面
      复制代码

二、函数的参数

1.形式参数与实际参数


  • 形式参数
    1. 函数在定义阶段括号内填写的参数
    2. def func(a):
    3.     pass
    复制代码
  • 实际参数
    1. 函数在调用阶段括号内填写的参数
    2. func(1)
    复制代码
  • 形参与实参的关系
    1. 1.形参类似于变量名 实参类似于数据值
    2.         def func(name):
    3.         pass
    4.     func('jason') #此时jason与name临时绑定
    5.    
    6. 2.函数在调用阶段 形参与实参会动态绑定 函数体代码运行结束会立刻解除绑定
    7.         def func(name):
    8.         print(name)
    9.     func(1)
    10.     func(2)
    11.     #第一次1与name绑定 函数体代码结束 解除绑定 name与2绑定
    复制代码
1.位置形参 与位置实参

位置形参:函数在定义阶段括号内从左往右依次填写的变量名
位置实参:函数在调用阶段括号内从左往右依次填写的数据值
  1. def func(a,b,c):# 位置形参
  2.     pass
  3. func(1,2,3)# 位置实参
  4. '''
  5. 1.实参可以是数据值,也可以是绑定了数据值的变量名。
  6. 2.位置实参在给位置形参传值的时候个数必须一致,不能多也不能少会报错。
  7. '''
复制代码
2.关键字实参与默认值形参(关键字形参)

关键字实参:函数在调用阶段括号内以什么等于什么传值(name=‘jason’)
  1. def func(a,b):
  2.     print(a,b)
  3. func(a=10,b=20) # 关键字实参  也可以:(b=20,a=10)
  4. func(10,b=20) # 位置实参与关键字实参可以一起使用
  5. '''
  6. 1.关键字实参给位置形参传值时打破了位置的限制,不用按照从左到右依次赋值。
  7. 2.需注意当位置实参和关键字实参一起用时,位置实参要在最后。
  8.      【简单在前,复杂在后,同复杂随便。但是需满足第三点】
  9. 3.调用函数时,一个形参只能接收一个实参
  10.    eg:
  11.     func(10,a=10) 此时由于位置形参a已经等于10了,关键字实参又给a赋了20的值,所以报错
  12. '''
复制代码
默认值形参:也可以叫做关键字形参 函数在定义阶段括号内以什么等于什么填写参数
用了默认值形参 用户传值就用用户传的值 用户不传就用默认的值
  1.         '默认值形参的定义也遵循【简单在前,复杂在后,同复杂随便】,但是一个形参只能接收一个实参'
  2.    def register(name,gender='男'): # 默认值形参
  3.        print(name,gender)
  4.    
  5. 1) register('jason') # 第二个可以不传实参
  6.    #结果为:jason 男
  7. 2) register('jason','女') # 第二个可以传位置实参
  8.    #结果为:jason 女
  9. 3) register('jason',gender='女') # 第二个可以传关键字实参
  10.    #结果为:jason 女
  11.    
  12. ————————————————————————————————————————————
  13. def register(gender='男'): # 默认值形参
  14.     print(gender)
  15. register() # 不传实参
  16. #结果为:男
复制代码
3.默认长形参(*与**在形参中的作用)

*在形参中:接收多余的位置参数 并整理成元组赋值给后面的变量名>> * args
  1. def func(*args):
  2.     print(args)
  3.    
  4. func()      # ()          没有参数给args所以是空元组
  5. func(1)     # (1,)
  6. func(1,2,3) # (1,2,3)
  7. ——————————————————————————————————
  8. def func(a,*args):
  9.     print(a,args)
  10. func()      # 结果会报错 因为a需要传一个参数
  11. func(1)     # 1 ()       1赋值给a,没有参数给args所以是空元组
  12. func(1,2,3) # 1 (2,3)    1赋值给a,2,3赋值给args组成元组
复制代码
**在形参中:接收多余的关键字参数并组成字典赋值给后面的>>  * * kargs
  1. def func(**kwargs):
  2.     print(kwargs)
  3.    
  4. func()         # {}   没有关键字实参给kwargs所以是空字典
  5. func(a=1)      # {'a':1}
  6. func(a=1,b=2)  # {'a':1,'b':2}
  7. ——————————————————————————————————
  8. def func(a,**kwargs):
  9.     print(a,kwargs)
  10.    
  11. func()          # 结果会报错 因为a需要传一个参数
  12. func(1)         # 1 {}
  13. func(1,b=22)    # 1 {'b':22}
复制代码
* * *结合使用:无论怎么传值都可以执行
  1. def func(*args,**kwargs):
  2.     print(args,kwargs)
  3.    
  4. func()       # () {}
  5. func(1,a=2)  # (1,) {'a':2}
  6. '位置实参给*结果是元组'
  7. '关键字实参给**结果是字典'
复制代码
4.可变长形参(* 与  ** 在实参中的作用)

*在实参中:相当于把列表、字典、字符串、元组、集合利用for循环取出一次性传给函数
  1. def func(a,b):
  2.     print(a,b)
  3.    
  4. l1=[1,2]
  5. s1='zz'
  6. d1={'a':1,'b':2} #字典在做循环时只有键参与
  7. func(*l1) # 结果为:1 2
  8. func(*s1) # 结果为:z z
  9. func(*d1) # 结果为:a b
  10. '当形参中没有*与**时,结果就是一个一个的数据值'
  11. ————————————————————————————————————
  12. def func(*args,**kwargs):
  13.     print(args,kwargs)
  14. l1=[1,2]
  15. s1='zz'
  16. d1={'a':1,'b':2} #字典在做循环时只有键参与
  17. func(*l1) # 结果为:(1, 2) {}
  18. func(*s1) # 结果为:('z', 'z') {}
  19. func(*d1) # 结果为:('a', 'b') {}
  20. '当形参中有*与**时,结果*就是元组,**就是字典'
复制代码
** 在实参中:仅针对字典 把字典的键值对当作关键字实参 一次性传给函数
  1. def func(**kwargs):
  2.     print(kwargs)
  3. d={'name':'jason','age':18}
  4. func(**d) # 结果为:{'name': 'jason', 'age': 18}
  5. '**d就等同于 name="jason" age=18'
复制代码
5.命名关键字参数
当要求形参必须使用关键字实参传值
  1. def func(*args,c,**kwargs):#注意c的位置要在**kwargs前
  2.     print(args,c,kwargs)
  3. func(1,2,c=3,a=4,b=5)
  4. #结果为:(1,2) 3 {'a':4,'b':5}
  5. '1和2给*args,关键字实参c=3给形参c,多余的关键字实参给**kwargs'
复制代码
三、名称空间

1.名称空间

名称空间就是用来存放变量名与数据值绑定关系的地方 也可以理解为是存储变量名的地方
  1. name = '张三'
  2. #底层原理:
  3. 1.在内存中申请一块空间存储'张三'
  4. 2.给'张三'绑定一个变量名name
  5. 3.此时变量名与数据值之间的绑定关系就会存放在名称空间中
  6. 4.后续使用变量名name就可以找到'张三'
  7. 'del 变量名   其实就是清除变量名与数据值的绑定关系'
复制代码
名称空间的分类


  • 内置名称空间
    python解释器运行时立刻创建的名称空间(里面存放内置的名字>>len()input()等
  • 全局名称空间
    py文件运行代码的过程中产生的名字就会储存在改空间中>>普通代码的变量名、分支循环的变量名、函数名、类名
  • 局部名称空间
    函数体代码/类体代码 执行过程中内部产生的名字都会被存放在该空间中
2.名称空间存户哦周期及作用范围(作用域)

名称空间存活周期:


  • 内置名称空间
    ​        创建:解释器运行                                  销毁:解释器结束
  • 全局名称空间
    ​        创建:py文件运行                                  销毁:py文件结束
  • 局部名称空间
    ​    创建:函数体/类体代码运行        销毁:函数体/类体代码结束
作用域:


  • 内置名称空间
    程序的任何位置都可以使用
  • 全局名称空间
    程序的任何位置都可以使用
  • 局部名称空间
    只能在局部名称空间使用 且不互通
3.名字的查找顺序
  1. a = '全局'
  2. def func():
  3.     a = '局部'
  4. func()
  5. print(a)
  6. #结果是:全局
  7. ——————————————————————————————————————————————
  8. #查找名字时要先确定自己在哪个名称空间
  9. 1.当前在局部名称空间时
  10.      局部名称空间 >> 全局名称空间 >> 内置名称空间
  11. 2.当前在全局名称空间时
  12.      全局名称空间 >> 内置名称空间
复制代码
4.局部名称空间案例


  • 相互独立的局部名称空间默认不能互相访问
    1. def func1():
    2.     name='jason'
    3.     print(age)
    4.    
    5. def func2():
    6.     age=18
    7.     print(name)
    8. #此时调用以上两个函数会报错,因为局部名称空间不互通
    复制代码
  • 局部名称空间嵌套
    1. def func1(): #1
    2.     x = 2 #3
    3.     def func2(): #4
    4.         x=3 #6
    5.         def func3(): #7
    6.             x=4 #9
    7.             print(x) #10
    8.         func3() #8
    9.     func2() #5
    10. func1() #2  结果为4  当函数嵌套调用时,一直打开到最内层的func3,则print(x)会从最内层往外查找 哪个最先有x就用哪个
    11. '这里需要注意:当func3里的x=4如果在print(x)下面 就会报错,因为函数在定义阶段名字的查找顺序就已经固定好了,它知道要在func3里查找 但是由于x=4还没定义出来 所以会报错。除非把func3中的x=4去掉才会往外一层找x=3'
    复制代码
5.global与nonlocal
了解:修改不可变类型(整型、浮点、字符串、元组)需用关键字声明
修改可变类型(列表、字典、集合)不需要关键字声明
不过经过实验可变类型加上关键字也不影响!所以不用纠结什么类型,都加上关键字也问题不大!!

  • 局部修改全局的数据 golabal
  1. 【不可变类型】:
  2. a = 10
  3. def func():
  4.     global a # 局部修改全局数据
  5.     a = 99   # 把全局a=99
  6. func()
  7. print(a) # 结果为:99
  8. ————————————————————————————————
  9. 【可变类型】:
  10. a = [1,2,3]
  11. def func():
  12.     a[0] = 99 # 把全局a列表索引0改为99
  13. func()
  14. print(a) # 结果为:[99,2,3]
复制代码

  • 内层局部修改外层局部的数据(函数嵌套)nonlocal
    1. 【不可变类型】:
    2. def outer():
    3.     a = 10
    4.     def inner():
    5.         nonlocal a # 内层局部改外层局部数据
    6.         a = 99     # 把外层局部a=99
    7.     inner()
    8.     print(a) # 结果为99
    9. outer()
    10. ————————————————————————————————
    11. 【可变类型】:
    12. def outer():
    13.     a = [1,2,3]
    14.     def inner():
    15.         a[0] = 99 # 把外层局部a列表索引0改为99
    16.     inner()
    17.     print(a) # 结果为:[99,2,3]
    18. outer()
    复制代码
四、装饰器

1.函数名的多种用法

打印函数名发现:函数名其实绑定的就是一个内存地址 该地址里存放着一段代码 函数名加括号就会找到该代码然后去执行

  • 可以当作变量名多次赋值
    1. def func():
    2.     pass
    3. a=b=func # 让a和b同时绑定func
    4. a()      # 此时a加括号可以调用func函数
    5. b()      # b加括号也可以调用func函数
    复制代码
  • 可以当作函数的参数
    1. def func():
    2.     print('我是另外一个函数func')
    3. def func1(a):
    4.     a()     # 2.传进来的func加括号就可以调用func函数
    5. func1(func) # 1.把func函数名当作参数传给func1
    6. #结果为:我是另外一个函数func
    复制代码
  • 可以当作函数的返回值
    1. def index():
    2.     print('index')
    3. def func():
    4.     print('func')
    5.     return index  # 返回值也可以写一个函数名
    6. res=func()        # 变量名res接收func的返回值 接收的就是index函数名
    7. print(res)        # 打印res就是index的内存地址
    8. res()             # res()就等同于index()
    复制代码
  • 可以当作容器类型的数据(列表、字典、元组、集合)
    1. def func():
    2.     pass
    3. l1 = [1,2,func] # 函数名可以放在列表中当作数据值
    4. l1[-1]()        # 列表取值加括号也可以调用函数
    5. ————————————————————————————————————
    6. def func():
    7.     print(111)
    8. d1 = {'1':func} # 函数名可以放在字典中当作值
    9. d1.get('1')()   # 字典取值加括号也可以调用函数
    复制代码
  • 编程套路
    1. #编程套路
    2. def register():
    3.     print('注册功能')
    4. def login():
    5.     print('登录功能')
    6. dict={
    7.     '1':register,
    8.     '2':login,
    9. }
    10. while True:
    11.     print("""
    12.     1.注册
    13.     2.登录
    14.     """)
    15.     choice=input('输入指令:').strip()
    16.     if choice in dict:
    17.         dict.get(choice)()
    18.     else:
    19.         print('指令不存在')
    复制代码
2.闭包函数

闭包函数:定义在函数内部的函数(函数嵌套) 且内部函数用到外部函数名称空间中的名字
闭包函数的作用:提供了另一种给函数传参的方式
  1. #给函数体传参的方式:
  2. 方式一:直接传参
  3. def register(name):
  4.     print(name)
  5. register('jason')
  6. #结果为:jason
  7. 方式二:闭包函数
  8. def outer(name):
  9.     def inner():
  10.         print(name) # 内部函数用外部函数的名字name
  11.     return inner
  12. res=outer('jason')  # 给外部函数传一个值jason并把返回值(内部函数名)赋给res
  13. res()               # res()等同于inner()
  14. #结果为:jason
复制代码
3.装饰器简介


  • 装饰器本质
    在不改变被装饰对象原来的调用方式和内部代码下 给被装饰对象添加新的功能
  • 装饰器原则
    不许修改 只许扩展
  • 储备知识 time模块
    1. #时间相关操作
    2. import time #导入一个时间模块
    3. print(time.time())# 1665482833.111403 距离1970年1月1日0时0分0秒所经历的秒数
    4. time.sleep(3)     # 让程序原地等待3秒
    5. _____________________________________________
    6. import time
    7. count = 0
    8. start_time = time.time() # 循环前获取一下时间为开始时间
    9. while count < 1000:
    10.     print(123)
    11.     count += 1
    12. end_time = time.time()   # 循环后获取一下时间为结束时间
    13. print('执行时间:', end_time - start_time) #结束时间-开始时间=共用时多久
    复制代码
4.装饰器推导流程

要求:1.再不改变被装饰对象原代码和调用方式的情况下给被装饰对象添加新的功能
​                  2.统计index函数的执行时间
  1. import time
  2. def index():
  3.     time.sleep(3)
  4.     print('这是index函数')
  5. def func():
  6.     time.sleep(1)
  7.     print('这是func函数')
  8. '''1.直接在调用index函数的前后添加代码'''
  9. start_time=time.time()
  10. index()
  11. end_time=time.time()
  12. print('函数的执行时间:',end_time-start_time)
  13. #缺陷:当index调用的地方较多时,反复拷贝代码太麻烦
  14. '''2.解决:相同的代码在不同地方反复执行,用函数包起来'''
  15. def get_time():
  16.     start_time = time.time()
  17.     index()
  18.     end_time = time.time()
  19.     print('函数的执行时间:', end_time - start_time)
  20. get_time()
  21. #缺陷1.函数体代码写死了,只能统计index函数的执行时间
  22. #缺陷2.改变了原代码的调用方式
  23. '''3.解决缺陷1:利用传参来让统计的函数写活'''
  24. def get_time(xx):
  25.     start_time = time.time()
  26.     xx()
  27.     end_time = time.time()
  28.     print('函数的执行时间:', end_time - start_time)
  29. get_time(func) #要统计哪个函数就把哪个函数当作参数传进来
  30. get_time(index) #要统计哪个函数就把哪个函数当作参数传进来
  31. '''4.解决缺陷2:直接传参不行就用闭包函数传参'''
  32. def outer(xx):
  33.     def get_time():
  34.         start_time = time.time()
  35.         xx()
  36.         end_time = time.time()
  37.         print('函数的执行时间:', end_time - start_time)
  38.     return get_time
  39. res=outer(index) #要统计哪个函数就把哪个函数当作参数传进来
  40. res()
  41. res=outer(func)  #要统计哪个函数就把哪个函数当作参数传进来
  42. res()
  43. #缺陷:改变了原代码的调用方式
  44. '''5.解决:把接收返回值的变量名写死,写成index'''
  45. def outer(xx):
  46.     def get_time():
  47.         start_time = time.time()
  48.         xx()
  49.         end_time = time.time()
  50.         print('函数的执行时间:', end_time - start_time)
  51.     return get_time
  52. index=outer(index) #要统计哪个函数就把哪个函数当作参数传进来
  53. index()
  54. #缺陷:只可以用无参函数,如果是有参函数会报错
  55. '''6.解决:给函数体内部加变量名去接收参数'''
  56. def func1(a):
  57.     time.sleep(2)
  58.     print('这是func1函数')
  59. def outer(xx):  #xx就是func1
  60.     def get_time(a):
  61.         start_time = time.time()
  62.         xx(a)
  63.         end_time = time.time()
  64.         print('函数的执行时间:', end_time - start_time)
  65.     return get_time
  66. index=outer(func1) #index就是get_time
  67. index(1) #index()就是get_time()
  68. #缺陷:有参函数如果是多个参数也不兼容
  69. '''7.解决:接收参数的变量名用可变长参数代替'''
  70. def func1(a):
  71.     time.sleep(2)
  72.     print('这是func1函数')
  73. def func2(a,b,c,d):
  74.     time.sleep(2)
  75.     print('这是func2函数')
  76.     return 123
  77. def outer(xx):  #xx就是func1
  78.     def get_time(*args,**kwargs):
  79.         start_time = time.time()
  80.         xx(*args,**kwargs)
  81.         end_time = time.time()
  82.         print('函数的执行时间:', end_time - start_time)
  83.     return get_time
  84. index=outer(func2) #index就是get_time
  85. index(1,2,3,4) #index()就是get_time()
  86. res=index(1,2,3,4)
  87. print(res)#结果是None 因为现在的index其实是get_time!
  88. #缺陷:如果被装饰的函数有返回值则会返回一个None
  89. '''8.找到真正要执行函数的位置让一个res去接收他的返回值(xx就是真正执行的)'''
  90. def func1(a):
  91.     time.sleep(2)
  92.     print('这是func1函数')
  93. def func2(a,b,c,d):
  94.     time.sleep(2)
  95.     print('这是func2函数')
  96.     return 123
  97. def outer(xx):  #xx就是func1
  98.     def get_time(*args,**kwargs):
  99.         start_time = time.time()
  100.         res=xx(*args,**kwargs)
  101.         end_time = time.time()
  102.         print('函数的执行时间:', end_time - start_time)
  103.         return res
  104.     return get_time
  105. index=outer(func2) #index就是get_time
  106. res=index(1,2,3,4)
  107. print(res)#结果就是对应函数的返回值!
复制代码

5.装饰器模板
  1. def func1():
  2.     print('func1')
  3.     return 111
  4. def func2(a):
  5.     print('func2')
  6.     return 222
  7. ——————————————————————————————————————————————————————
  8. #装饰器模板:
  9. def outer(func): #func用来绑定真正被装饰的对象内存地址
  10.     def inner(*args,**kwargs):
  11.         #执行被装饰对象之前做的额外操作
  12.         res = func(*args,**kwargs)
  13.         #执行被装饰对象之后做的额外操作
  14.         return res
  15.     return inner
  16. ————————————————————————————————————————————————————————
  17. #调用:
  18. 【无参】
  19. func1=outer(func1) #左边func1就是inner 右边的func1就是把真正函数名当参数传给装饰器
  20. res=func1()  #func1()就是inner() 并接收inner的返回值  inner的返回值就是真的函数的返回值
  21. print(res)   #打印真正被装饰的函数的返回值
  22. 【有参】
  23. func2=outer(func2)
  24. res=func2(1)
  25. print(res)
复制代码
6.装饰器语法糖

语法糖会自动将下面紧挨着的函数名当作第一个参数自动穿给@函数调用
  1. 【定义】
  2. def outer(func_name):
  3.     def inner(*args, **kwargs):
  4.         print('执行被装饰对象之前可以做的额外操作')
  5.         res = func_name(*args, **kwargs)
  6.         print('执行被装饰对象之后可以做的额外操作')
  7.         return res
  8.     return inner
  9. _________________________________
  10. @outer  # 等同于调用阶段的func=outer(func)
  11. def func():
  12.     print('这是func函数')
  13.     return '111func'
  14. @outer  # 等同于调用阶段的index=outer(index)
  15. def index():
  16.     print('这是index函数')
  17.     return '111index'
  18. _________________________________
  19. 【调用】
  20. #func = outer(func) 加了语法糖则不需要该操作
  21. func()
  22. #index=outer(index) 加了语法糖则不需要该操作
  23. index()
复制代码
7.多层语法糖
  1. def outter1(func1): #func1=wrapper2
  2.     print('加载了outter1')
  3.     def wrapper1(*args, **kwargs):
  4.         print('执行了wrapper1')
  5.         res1 = func1(*args, **kwargs)
  6.         return res1
  7.     return wrapper1
  8. def outter2(func2): #func2=wrapper3
  9.     print('加载了outter2')
  10.     def wrapper2(*args, **kwargs):
  11.         print('执行了wrapper2')
  12.         res2 = func2(*args, **kwargs)
  13.         return res2
  14.     return wrapper2
  15. def outter3(func3): # func3=真正的index
  16.     print('加载了outter3')
  17.     def wrapper3(*args, **kwargs):
  18.         print('执行了wrapper3')
  19.         res3 = func3(*args, **kwargs)
  20.         return res3
  21.     return wrapper3
  22. @outter1  # index=outer1(wrapper2)>>返回值为wrapper1
  23. @outter2  # outer2(wrapper3)>>返回值为wrapper2
  24. @outter3  # outer3(index)>>返回值为wrapper3
  25. def index():
  26.     print('from index')
  27. index()
  28. '''
  29. 运行结果:
  30.    加载了outter3
  31.    加载了outter2
  32.    加载了outter1
  33.    执行了wrapper1
  34.    执行了wrapper2
  35.    执行了wrapper3
  36.    from index
  37. '''
复制代码
注意
1.多层语法糖的顺序是从下往上的
2.语法糖h会自动将他紧挨着的函数名当作参数传给@的函数调用
3.多次语法糖在每次执行后如果上面还有语法糖则直接将返回的数据传给上面的语法糖
​        如果上面没有语法糖后变形为index = outer1(wrapper2)

8.有参装饰器

当装饰器中需要额外的参数的时候就要用到有参装饰器
'函数名加括号执行优先级最高'
有参装饰器流程:
@outer('1')
1.先看函数名加括号的执行 outer('1')
2.再看语法糖的操作 @outer
  1. # 校验用户是否登录装饰器
  2. def outer(mode): #mode='1'
  3.     def login_auth(func):
  4.         def inner(*args,**kwargs):
  5.             username=input('username>>:').strip()
  6.             password=input('password>>:').strip()
  7.             if mode=='1':
  8.                 print('数据来源写死')
  9.             elif mode=='2':
  10.                 print('数据来源于文本文件')
  11.             elif mode=='3':
  12.                 print('数据来源于字典')
  13.             #res=func(*args,**kwargs) #此处不写则不会执行真正index里的print
  14.             #return res               #此处不写则不会执行真正index里的print
  15.         return inner
  16.     return login_auth
  17. @outer('1') #变形为语法糖后就是@login_auth,语法糖把最近的函数名变成参数传给outer:index=login_auth(真正的index)
  18. def index():
  19.     print('from index')
  20. index()
  21. @outer('2')
  22. def func():
  23.     print('from func')
  24. func()
复制代码

9.有参装饰器与无参装饰器模板

无参:
  1. def outer(func):
  2.     def inner(*args,**kargs):
  3.         #执行装饰器之前做的操作
  4.         res = func(*args,**kargs)
  5.         #执行装饰器之后做的操作
  6.         return res
  7.     return inner
  8. @outde
  9. def index():
  10.         pass
复制代码
有参:
  1. def oouter(mode)
  2.     def outer(func):
  3.         def inner(*args,**kargs):
  4.             #执行装饰器之前做的操作
  5.             res = func(*args,**kargs)
  6.             #执行装饰器之后做的操作
  7.             return res
  8.         return inner
  9.     return outer
  10. @outde(1)
  11. def index():
  12.         pass
复制代码
10.装饰器修复技术

help(函数名)
  1. #补充知识:
  2. def func():
  3.     """这是index函数"""
  4.     pass
  5. help(func) #会告诉这个名字的基本信息
  6. #结果为:func()
  7. #            这是index函数
复制代码
让装饰器看起来更逼真:
  1. from functools import wraps # 导入一个wraps模块
  2. def outer(func_name):
  3.     @wraps(func_name)  # 仅仅是为了让装饰器更逼真(用户用help方法也看不出来)
  4.     def inner(*args, **kwargs):
  5.         """我是inner 我擅长让人蒙蔽"""
  6.         res = func_name(*args, **kwargs)
  7.         return res
  8.     return inner
  9. @outer
  10. def func():
  11.     """我是真正的func 我很强大 我很牛 我很聪明"""
  12.     pass
  13. help(func)#help查看该函数真正信息就会发现是真正的func函数信息
  14. '如果不加wraps模块查看的就是inner函数信息'
  15. print(func)#<function func at 0x000002DB3568EE50>
复制代码
五、递归函数

1.递归函数

使用递归函数注意:

  • 函数直接或者间接调用自己就叫递归调用
  • 每次调用都必须比上一次简单 且要有一个明确的结束条件
递归函数的应用场景:

  • 递推:一层一层往下寻找答案
  • 回溯:根据明确的条件往上得出结果
    1. 1.递归——直接调用:('自己调自己')
    2. def index():#1
    3.     print('这是index函数')#3
    4.     index()#4
    5. index()#2
    6. #执行顺序:12343434一直重复
    7. ——————————————————————————————————————————
    8. 2.递归——间接调用:('别人调我,我调别人')
    9. def index():#1
    10.     print('这是index函数')#6
    11.     func()#7
    12. def func():#2
    13.     print('这是func函数')#4
    14.     index()#5
    15. func()#3
    16. #执行顺序:123456745674567一直重复
    复制代码
    pycharm允许函数最大调用的次数是1000 实际略有偏差
    1. count = 0
    2. def index():
    3.     print('这是index')
    4.     global count
    5.     count + = 1
    6.     print(count)
    7.     index()
    8. index()
    9. #结果为:会一直执行到996或997
    复制代码
练习:
  1. 问A年龄,A说我比B大2岁
  2. 问B年龄,B说我比C大2岁
  3. 问C年龄,c说我比D大2岁
  4. 问D年龄,D说我比E大2岁
  5. 问E年龄,E说我18岁
  6.     """
  7.     get_age(5) = get_age(4) + 2
  8.     get_age(4) = get_age(3) + 2
  9.     get_age(3) = get_age(2) + 2
  10.     get_age(2) = get_age(1) + 2
  11.     get_age(1) = 18
  12.     """
  13. def get_age(n):
  14.     if n == 1:
  15.         return 18
  16.     return get_age(n-1) + 2
  17. res = get_age(5)
  18. print(res)
复制代码
六、算法、三元表达式、各种生成式

算法:解决问题的有效方法
应用场景:推荐算法(视频推送)、成像算法(线上试衣)
常见算法:二分法、冒泡、快排、插入...等等
1.二分法

二分法:不断地对数据进行切割分成两份进行判断 只要找到张耀的结果
要求:待查找的数据必须是有序的
缺陷:因为是从中间开始切割 开头或者结尾查找效率低
[code]#eg:用算法二分法判断82在不在列表中,如果在则取出l1=[11,23,35,43,55,62,75,82,94]def get_num(l1,num):    #添加一个结束条件    if len(l1)==0:        print('没找到')        return    #1.获取列表中间数据的索引值    middle=len(l1)//2  # 整除:要除完后的整数 4    #2.比较目标82与中间数4的大小    if num>l1[middle]:  # 82>l1[4]        #切片保留右半边列表        right_l1=l1[middle+1:]  # 索引4的55比较过 所以切索引4+1        print(right_l1)#[62,75,82,94]        return get_num(right_l1,num)    elif num

本帖子中包含更多资源

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

x

举报 回复 使用道具