一、函数
1. 函数定义
1.1 先定义, 后调用
函数定义:
"""
def my_fun(): # my_fun --> 函数名
'''
文档描述
'''
函数体
return 值
"""
1.1.1 三种定义方式
定义函数不运行函数体代码, 但是会检查函数体语法
# 方式一: 无参函数 ---> 函数不需要接受值, 就可以完成所需功能
def func_1():
print('122')
# 方式二: 有参函数 ---> 需要接受外部传值
def func_2(age):
print(age)
# 方式三: 空函数: 函数体代码为pass ---> 构思代码使用
def func_3(age):
pass
1.1.2 三种调用方式
通过函数名找到函数所在内存地址, 加()触发函数体代码执行
# 方式一: 语句形式, 只调用函数
func()
# 方式二: 表达式形式(赋值表达式, 数学表达式): 取函数的返回值
func()
# 方式三: 函数可以当成另一个函数的参数
func()
1.1.3 三种返回值形式
return 后面的代码不执行, 并将return后的值当做运行结果返回
# 方式一: 返回None
func()
# 方式二: 返回一个值
func()
# 方式三: 返回多个值, 用 ',' 分割开, return一个元组
func()
2. 参数
位置参数必须放在放在关键字参数之前, 不能为同一个形参重复传值
2.1 形参: 在定义函数时定义的参数叫形式参数, 简称形参, 相当于变量名
2.2 实参: 在调用函数时, 传入函数的值称为实际参数, 简称实参, 相当于变量值
# 方式一:
fun(1, 2)
# 方式二:
a = 1
b = 2
func(a, b)
# 方式三:
func(int('1'), 2)
2.3 位置参数
位置形参:
函数定义时, 按从左到右的顺序依次定义的参数称之为位置参数
特点: 必须被传值, 不能多也不能少
位置实参:
函数调用时, 按从左到右的顺序依次传入的值
特点: 按照顺序与形参一一对应
2.4 关键字参数
关键字实参:
函数调用时, 按照key=value的形式传入值
特点: 可以完全不参照顺序给函数传值
2.5 默认形参
在定义函数阶段, 就已经被赋值的形参, 称之为默认参数
特点: 在定义阶段就已经被赋值, 在调用阶段就可以不赋值
2.6 可变长参数
指的是在函数调用时, 传入值的个数是不固定的 *args/**kwargs
*args: 用来接收溢出的位置实参 —> 元组形式接收
**kwargs: 用来接收溢出的关键字实参 —> 字典形式接收
**特点: **
================================================
(以下了解内容)
命名关键字参数:
在定义函数是时, *后定义的参数称之为命名关键字参数
def func(x, y, *, a, b):
print(x, y)
print(a, b)
特点: 命名关键字参数传参必须按照key=value的形式
================================================
3. 名称空间与作用域
名称空间加载顺序: 内置名称空间 > 全局名称空间 > 局部名称空间
名称空间销毁顺序: 局部名称空间 > 全局名称空间 > 内置名称空间
名字查找顺序: 当前所在位置向上一层一层查找
名称空间的嵌套关系是以定义阶段为准, 与调用位置无关(名称空间只有优先级之分, 本身无嵌套关系, 说嵌套是帮助理解)
LEGB: L: local E: enclosing G: global B: builtin
3.1 名称空间
存放名字的地方, 是对栈区的划分
3.1.1 局部名称空间(局部范围)
在调用函数时, 运行函数体代码时产生的名字
存活周期:
3.1.2 全局名称空间(全局范围)
运行顶级代码产生的名字
存活周期: python文件执行产生, python文件运行完毕后销毁
3.1.3 内置名称空间(全局范围)
存放python解释器内置的名字
存活周期: python解释器启动产生, python解释器关闭销毁
3.2 作用域
3.2.1 全局作用域(内置名称空间, 全局名称空间)
特点: 全局存活, 全局有效, 被所有函数共享
3.2.2 局部作用域(局部名称空间)
特点: 临时存活, 局部有效, 函数内有效
3.3 global和nonlocal
global: 声明变量名是全局名, 不需要再造变量名
nonlocal: 修改函数外层函数包含的变量名对应的值
4. 函数嵌套
函数对象: 可以把函数当成变量用(可以赋值; 可以把函数当参数传给另一个函数; 可以当做另一个函数的返回值; 可以当做容器类型的一个元素)
4.1 函数嵌套调用
在调用一个函数的过程中又调用其他函数
4.2 函数嵌套定义
在函数内定义其他函数
4.3 闭包
闭包函数 = 名称空间与作用域 + 函数嵌套 + 函数对象
核心点: 名字的查找关系是以函数定义阶段为准的
‘闭’函数指的是该函数的内嵌函数, ‘包’函数是指该函数包含对外层函数作用域名字的引用(不是对全局作用域)
# 定义闭包函数
def fun_1():
x = 11
def fun_2():
print(x)
return fun_2
5. 装饰器
开放封闭原则: 对拓展功能是开放的, 对修改源代码是封闭的
装饰器: 定义一个函数(类), 该函数用来装饰其他函数, 即为其他函数增加额外的功能
import time
def index_l(x, y):
time.sleep(3)
print(x, y)
def home(name):
print(name)
def outter(func):
def wrapper(*args, **kwargs):
# 在不修改index_l源代码和调用方式的前提下增加函数运行时间的功能
start_time = time.time()
res = func(*args, **kwargs)
stop_time = time.time()
print(stop_time - start_time)
return res
return wrapper
index_l = outter(index_l)
home = outter(home)
index_l(1, '222')
home('12d')
语法糖:
import time
def timmer(func):
def wrapper(*args, **kwargs):
# 在不修改index_l源代码和调用方式的前提下增加函数运行时间的功能
start_time = time.time()
res = func(*args, **kwargs)
stop_time = time.time()
print(stop_time - start_time)
return res
return wrapper
@timmer
def index_l(x, y):
time.sleep(3)
print(x, y)
@timmer
def home(name):
print(name)
index_l(1, '222')
home()
# 无参装饰器模板
from functools import wraps
def outter(func):
@wraps(func) # 将原函数的属性赋值给wrapper函数
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
return res
# 手动将原函数的属性赋值给wrapper函数
# wrapper.__name__ = func.__name__
# wrapper.__name__ = func.__doc__
return wrapper
# 有参装饰器模板
def auth(x):
def deco(func):
def wrapper(*args, **kwargs):
if x == 1:
res = func(*args, **kwargs)
return res
else:
print('被装饰函数不运行')
return wrapper
return deco
6. 迭代器与生成器
迭代器: 指的是迭代取值的工具, 迭代是一个重复的过程, 每次重复都是基于上一次结果而继续的, 单纯的重复不是迭代(不依赖于索引取值)
可迭代对象: 内置有.__ iter __ 方法的都是可迭代对象
l = [1, 2, 3, 4]
l_iterator = l.__iter__()
while True:
try:
print(l_iterator.__naex__())
except StopIteration:
break
迭代器对象: 内置有.__ next __ 方法并且内置有.__ iter 方法的对象(. __ next ():得到下一个值, . __ iter (): 得到的是迭代器本身)
for 循环的工作原理:
1. 调用.__ __iter__ __()得到一个迭代器对象__
2. __迭代器对象.__ __next__ __()拿到一个返回值, 然后将该返回值返回赋值给变量名(i)
3. 循环步骤2, 直到抛出一个异常, for循环捕捉这个异常然后结束循环
迭代器优缺点:
优点: 节省内存; 不受制于索引
缺点: 只能取下一个值; 除非取完, 否则无法获取迭代器的长度(一次性)
生成器(自定义迭代器)
在函数内一旦存在 yield 关键字, 调用函数时不会执行函数体代码, 会返回一个生成器对象, 生成器就是自定义迭代器
def func():
# yield 可返回多个值
print('1...')
yield 1
print('2...')
yield 2
g = func()
print(g)
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
next(g)
生成器应用:
叠加多个装饰器:
# 加载顺序自下而上, 执行顺序自上而下
def outer_1(func_1):
def wrapper_1(*args, **kwargs):
print('outer_1.index_1 正在运行....')
res_1 = func_1(*args, **kwargs)
return res_1
return wrapper_1
def outer_2(func_2):
def wrapper_2(*args, **kwargs):
print('outer_2.index_2 正在运行....')
res_2 = func_2(*args, **kwargs)
return res_2
return wrapper_2
def deco_1(num):
def outer_3(func_3):
def wrapper_3(*args, **kwargs):
print('deco_1.outer_3.index_3 正在运行....', num)
res_3 = func_3(*args, **kwargs)
return res_3
return wrapper_3
return outer_3
@outer_1
@outer_2
@deco_1(333)
def index_demo(x, y):
print(x, y)
return x, y
print(index_demo(1, 4))
yield的表达式形式
def func_1(num):
print(num, '是传入的参数.....', sep='')
while True:
x = yield 'yield 的返回值'
print(x, '是yield接收到的值......', sep='')
g = func_1(222)
print(g.send(None)) # 等同于 next(g)
print(g.send('111'))
三元表达式
三元: 条件 条件成立 条件不成立
x = 3
y = 2
res = x if x > y else y
print(res)
列表生成式
l = [1, 2, 3, 4, 5]
new_l = [num for num in l]
new_l = [num for num in l if num > 2]
其他生成式
# 字典生成式
items = [('name', 'xxx'), ('age', 18), ('gender', 'male')]
res = {k: v for k, v in items if k != 'gender'}
print(res)
# 集合生成式
items = [('name', 'xxx'), ('age', 18), ('gender', 'male')]
res = {k for k, v in items if k != 'gender'}
print(res)
# 生成器表达式
g = (i for i in range(10) if i > 3)
print(next(g))
# 统计文件字符个数
with open('name_file.txt', mode='r', encoding='utf-8') as f:
# # 方法一
# res = 0
# for line in f:
# res += len(line)
# print(res)
# # 方法二
# res = sum([len(line) for line in f])
# print(res)
# 方法三: 效率最高
res = sum(len(line) for line in f) # sum(len(line) for line in f) 等同于 sum((len(line) for line in f))
print(res)
7. 递归
递归的本质是循环
# 直接调用函数本身
def func_1():
print('这是一个递归函数, 调用本身')
func_1()
# 间接调用函数
def func_1():
print('func_1 调用了 func_2')
func_2()
def func_2():
print('func_2 调用了 func_1')
func_1()
递归的两个阶段
回溯: 一层一层调用
递推: 满足某种结束条件, 结束调用, 然后一层一层返回
8. 函数类型提示功能
python语言是解释型, 强类型, 动态型的语言
# : 后面添加提示信息
def func(name: str, age: int, hobbies: tuple)->int: # -> 后面是返回值的类型
print(name, age, hobbies)
return 2333333
# 添加默认值
def func(name: str='xx', age: int=18, hobbies: tuple=('111', '222'))->int: # -> 后面是返回值的类型
print(name, age, hobbies)
return 2333333
# 查看函数提示信息
print(func.__annotations__)