1.函数
1.1 数的返回值
- 返回值就是函数执⾏以后返回的结果
- 通过return来指定函数的返回值 return后⾯可以跟任意对象,返回值甚⾄可以是⼀个函数
return后的代码都不会执行,return一旦执行,函数自动结束
def fun2():
# print(111)
# return
# print('hahah')
for i in range(5): # range(0, 5, 1) 左闭右开型
if i == 3:
# break 用来退出当前循环
# continue 用来跳过当次循环
return
print(i)
print('循环执行完毕')
fun2()
# fun 是函数名(函数对象) 打印fn就是打印函数对象的地址
# fun() 是调用函数 打印fun()就是在打印fun()的返回值
1.2. ⽂档字符串
- help()是Python中内置函数,通过help()函数可以查询Python中函数的⽤法 在定义函数时,可以在函数内部编写⽂档字符串,⽂档字符串就是对函数的说明
def fun(a, b, c):
"""
这是一个文档字符串的示例
这个函数是做什么用的。。。。
:param a: 作用 类型 默认值
:param b: 作用 类型 默认值
:param c: 作用 类型 默认值
:return: 需不需要返回值
"""
return 123
help(fun)
help(print)
1.3 函数的作⽤域 作⽤域(scope)
- 作⽤域指的是变量⽣效的区域
- 在Python中⼀共有两种作⽤域
- 全局作⽤域
- 全局作⽤域在程序执⾏时创建,在程序执⾏结束时销毁
- 所有函数以外的区域都是全局作⽤域
- 在全局作⽤域中定义的变量,都是全局变量,全局变量可以在程序的任意位置进⾏访问
- 函数作⽤域
- 函数作⽤域在函数调⽤时创建,在调⽤结束时销毁
- 函数每调⽤⼀次就会产⽣⼀个新的函数作⽤域
- 在函数作⽤域中定义的变量,都是局部变量,它只能在函数内部被访问
- 全局作⽤域
函数内部的变量只能在函数内部访问,不能在函数外部访问
b = 456
def fun():
global a # 声明a是全局变量
a = 123
print('函数内部 a = ', a)
print('函数内部 b = ', b)
def fun1():
print('函数fun1内部 a = ', a)
print('函数fun1内部 b = ', b)
fun1()
fun()
print('函数外部 a = ', a)
print('函数外部 b = ', b)
1.4 命名空间
• 命名空间实际上就是一个字典,是一个专门用来存储变量的字典
• locals()用来获取当前作用域的命名空间
• 如果在全局作用域中调用locals()则获取全局命名空间,如果在函数作用域中调用locals()则获取函数命名空间
• 返回值是一个字典
#locals()用来获取当前作用域的命名空间,返回一个字典
a = 123
b = 456
c = 789
# space = locals()
# space['d'] = 100
# print(space)
def fun():
a = 1
b = 2
c = 3
# space = locals()
space = globals()
print(space)
fun()
-------------------------------------------------------
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002991A81F880>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/命名空间.py', '__cached__': None, 'a': 123, 'b': 456, 'c': 789, 'fun': <function fun at 0x000002991AA5E280>}
1.5 递归函数
• 递归是解决问题的一种方式,它的整体思想,是将一个大问题分解为一个个的小问题,直到问题无法分解时,在去解决问题
• 递归式函数有2个条件
• 1. 基线条件 问题可以被分解为最小问题,当满足基线条件时,递归就不执行了
• 2. 递归条件 可以将问题继续分解的条件
# 递归函数的两个条件
# 1. 基线条件 问题可以被分解为最小的问题,当满足基线条件的时候,再去解决问题 (设定的最大递归深度)
# 2. 递归条件 将问题继续分解的条件
# 10! n! fun(n) 是求n的阶乘的函数
# 10! = 10 * 9! n*(n-1)! n * fun(n-1) 求n-1的阶乘的函数
# 9! = 9 * 8!
# .....
# 2! = 2*1!
# 1! = 1
def fun(n): # fun求n的阶乘
# 基线条件
if n == 1:
return 1
# 递归条件
return n * fun(n-1)
res = fun(10) # res = 10*fun(9)/10*9*fun(8)/
print(res)
----------------------------------------------------
3628800
2.高阶函数
2.1 高阶函数
• 接收函数作为参数,或者将函数作为返回值返回的函数就是高阶函数
2.2 闭包
- 将函数作为返回值也是高阶函数我们也称为闭包
- 闭包的好处
• 通过闭包可以创建一些只有当前函数能访问的变量
• 可以将一些私有数据藏到闭包中 - 行成闭包的条件
• 函数嵌套
• 将内部函数作为返回值返回
• 内部函数必须要使用到外部函数的变量
#• 行成闭包的条件
#• 函数嵌套
#• 将内部函数作为返回值返回 返回的是函数对象
#• 内部函数必须要使用到外部函数的变量或参数
# 闭包的作用: 保存外部函数的变量不被销毁
def fun_out(num1):
# 定义一个内部函数
def fun_inner(num2):
# 内部函数用到了外部函数的变量或参数(num1)
res = num1 + num2
print(res)
print(fun_inner.__closure__)
print(id(num1))
fun_inner(2)
print(id(num1))
return fun_inner
f = fun_out(1)
print(id(fun_out))
f(3)
2.3 装饰器的引入
- 我们可以直接通过修改函数中的代码来完成需求,但是会产生以下一些问题
- 如果修改的函数多,修改起来会比较麻烦
- 不方便后期的维护
- 这样做会违反开闭原则(ocp)
- 程序的设计,要求开发对程序的扩展,要关闭对程序的修改
def add(a, b):
return a + b
def qiuji():
print(111)
# fun是做装饰 并不是装饰器
def fun(fn, *args, **kwargs):
print('程序开始执行')
r = fn(*args, **kwargs)
print('程序执行结束')
return r
print(fun(add, 1, 2))
2.4 装饰器的使用
- 通过装饰器,可以在不修改原来函数的情况下来对函数进行扩展
- 在开发中,我们都是通过装饰器来扩展函数的功能的
装饰器是一个特殊的闭包
# 它符合闭包的三大构成条件
# 通用装饰器
def fun_out(fn):
def fun_inner(*args, **kwargs):
print('函数开始执行')
r = fn(*args, **kwargs)
print('函数执行结束')
return r
return fun_inner
@fun_out # 装饰器语法糖的写法
def add(a, b):
return a + b
r = add(1, 2)
print(r)
@fun_out
def qiuji():
print(111)
qiuji()
# 语法糖: @fun_out 等价于 fun_out(fn)