Skip to content

Latest commit

 

History

History
305 lines (205 loc) · 7.86 KB

248-562560-函数总结.sy.md

File metadata and controls

305 lines (205 loc) · 7.86 KB
show version enable_checker
step
1.0
true

函数总结

函数总结

  • 这次我们要从头回顾函数的各个方面
  • 最开始我们还不知道什么是函数

图片描述

  • 函数就是套路
    • 一段代码需要反复执行
    • 我们把他封装成一个代码块
    • 起一个名字
    • 代表这段代码

图片描述

  • 以后我们就可以通过调用(call)函数
  • 来反复执行这段代码
  • 函数也可以接受一些参数

参数

  • 函数定义的时候
    • 有形参列表
  • 调用的时候
    • 有实参可以传进来
  • 这经历了一个赋值的过程
    • 将实参的值赋给函数的形参
    • 实参的值一般是一个对象的引用
  • 字符串、整型、浮点型传进函数内部后
    • 不会影响外面的变量

图片描述

  • 列表、集合等容器如果再函数内部改变后
    • 会影响外面的指向同一地址的变量

图片描述

  • 参数是函数内部的局部变量
  • 局部变量和全局变量有不同的作用域(scope)

作用域

  • 主程序中定义的是模块全局(global)可见的
  • 函数中定义的和函数形参是函数局部(local)可见的

图片描述

  • 如果同名
  • 局部的会屏蔽(shadow)全局的

图片描述

  • 可以将局部变量声明为全局(global)
  • 就可以在主程序使用局部变量了

函数也是对象

  • 函数是一个函数类的对象

图片描述

  • code object里面有这个函数的各种信息
    • 函数名
    • 内部变量数量和元组
    • 字节码

图片描述

  • 还可以把函数对象作为一个实参
  • 传递给别的函数的形参

名字空间(namespace)

图片描述

  • 变量名都是a
  • 但是可以用名字空间进行区分
  • 我们有很多变量名来自于内建(__builtins__)

模块

图片描述

  • python本来就有好多的包
  • 可以方便我们使用
  • 我们自己也能打包

打包

  • 一个文件夹里面可以有多个py模块
  • 文件夹下面的 __init__.py 就是初始化模块的模块
  • 会在一开始执行

图片描述

  • 还可以为模块和函数写文档字符串

图片描述

  • 然后把文件或文件夹放进$PYTHONPATH
  • 就可以反复调用了

主程序

  • 模块里面有主程序__main__.py
  • 运行模块就是运行主程序

图片描述

  • 也可以在py文件中直接判断
  • 通过判断__main__==__name__
    • 有些代码是只有顶级的时候才执行的
    • 作为导入模块不需要执行这些代码

返回值

  • 每个函数都会有返回值
  • 一般是函数运行的结果

图片描述

  • 如果没有返回值
  • 那么函数在执行完最后一条语句之后
  • 默认返回的一个 NoneType 的值 None

函数的重写和重载

  • 重写是旧的覆盖新的
  • 把原来的抹去

图片描述

  • 重载是同一个函数名
  • 不同的参数数量或类型
  • 调用的时候可以根据形参情况进入相应的函数体

函数可以嵌套地调用

  • 画松树可以分成几步来完成

图片描述

  • 参数也可以不止一个
  • 比如修改树冠的颜色
  • 还可以
    • 为树冠设置默认值绿色
    • 树冠大小设置默认值5

参数可以从命令行直接来

  • 用的是argparse这个包

图片描述

  • 引用这个包之后
  • 可以为python定义各种参数
  • 控制参数
    • 类型
    • 范围
    • 默认值等等

函数自己调用自己

  • 函数自身的嵌套调用

图片描述

  • 函数的递归调用

图片描述

  • 我们了解了调用栈上的帧

观察栈帧

  • 可以输出frame对象的内容
  • 观察栈帧

图片描述

  • 可以用VizTracer观察栈帧的情况

图片描述

递归 vs 循环

  • 递归在数学上很完美
  • 但是对于调用堆栈消耗很大
  • 如何比较了两者呢?
  • 了解了timeit可以计数

图片描述

  • 递归有太多的重复运算
  • 这些重复运算可以用lru_cache消除

函数的嵌套定义

  • 函数内部可以定义函数

图片描述

  • 将具体操作放在函数中的函数里面
  • 可以屏蔽外面的干扰
  • 内部函数的变量可以通过nonlocal被外层代码访问
  • 总结三种作用域
    • local 本地可见 (默认)
    • global 全局可见
    • nonlocal 非本地可见(上一层函数也可见)

图片描述

  • 函数内部的同名函数变量会屏蔽(shadow)外层的变量名
    • enclosing_function 中的 _fibo 不是外面全局的 _fibo
    • enclosing_function 中的 _fibo 屏蔽了外面全局的 _fibo
  • 这是持续集成

因数

  • 先求的是因数集合
  • 然后在因数集合中找到质因数
  • 质因数求解过程中发现开方的好处
  • 大幅度提高效率
  • 然后再求解最大公约数的时候
  • 发现了辗转相除法的好处
  • 极大的提升了效率
  • 有的时候模块还需要打破重组

图片描述

代码提示

  • python虽然是动态类型编程语言
  • 但是也有类型提示
def get_factor_set(num: int) -> set:
    s: set = {1}
    for i in range(2, num + 1):
        if num % i == 0:
            s.add(i)
    return s

def gcd(n1: int, n2: int) -> set:
    s1: set = get_factor_set(n1)
    s2: set = get_factor_set(n2)
    gcd: set = s1.intersection(s2)
    return max(gcd)

print(gcd(3600,4096))
  • 可以进行静态类型检查(mypy)
  • 还可以静态语言分析(pylint)
    • 使得代码符合pep8

形参分类

  • 形参可以分成
    • 纯位置
    • 两可
    • 纯关键字

图片描述

  • 还可以接受元组*args作为形参
    • 实现不定长的位置参数列表
  • 还可接受字典**kwargs作为形参
    • 实现不定长的关键字参数列表

lambda表达式

  • lambda表达式会形成一个匿名函数
  • 直接写在实参的位置

图片描述

  • 简单明确

函数总结

  • 我们这次学习了很多函数相关的内容
    • 函数就是套路
    • 可以让代码一次次地执行
    • 用形参来接收实参
    • 完成套路之后返回
    • 函数可以层层嵌套
    • 也就是层层套路
    • 甚至递归函数
  • 通过函数我们实现了代码的复用
  • 各种类型都有很多的函数作为辅助
  • 下次我们看点什么?🤔
  • 下次再说👋