函数
函数:用来完成特定功能的代码块,类似于工具,可以重复去使用
为什么要有函数
- 避免代码的冗余
- 让程序代码结构更加清晰
- 让代码具有复用性,便于维护
定义函数的语法
def 函数名(参数列表):
函数体
return 返回值
目的
1. 功能的单一化
2. 函数内部需要外部的资源,通过函数的参数来实现
3. 函数执行后的结果需要告诉外界,通过返回值告诉给外界
调用函数的方法
函数名()
- 函数的参数: 实参与形参
def fn(形参们):
pass
fn(实参们)
形参:定义函数,在括号内声明的变量名,用来结束外界传来的值
实参:调用函数,在括号内传入的实际值,值可以为常量、变量、表达式或三者的组合
注:形参随着函数的调用而产生,随着调用结束而销毁(有特例)
实参分类
位置实参:必须按照顺序给形参传值
关键字实参:按照关键字给形参传值,所以顺序可以颠倒
# 注:位置实参、关键字实参共存是,关键字实参必须出现在所有位置实参之后
形参分类
位置形参:位置实参与关键字实参都可以对其传参
默认形参:位置实参与关键字实参都可以对其传参,也可以不被传参
可变长位置形参:接收位置形参、默认形参没有接收完的所有位置实参
无初值关键字形参:只能由关键字实参传值
有初值关键字形参:只能由关键字实参传值,也可以不被传值
可变长关键字参数:接收两种关键字形参没有接收完的所有关键字实参
注:各种形参出现的先后
位置形参 - 默认形参 - 可变长位置形参 - 无|有初值关键字形参 - 可变长关键字参数
#示例
def fn(a, b, c=10, *args, d, e=20, f, **kwargs):
pass
# 位置形参:a、b
# 默认形参:c
# 可变长位置形参:args
# 无初值关键字形参:d、f
# 有初值关键字形参:e
# 可变长关键字参数:kwargs
可变参数的整体使用
# 1、可变位置形参以元组方式接收值
# 如:接收10,20,30三个数
def fn1(*args):
print(args) # (10, 20, 30)
# 第一种传参
fn1(10, 20, 30)
# 第二种传参
t = (10, 20, 30) # 单列集合及字符串类型都可以
fn1(*t)
# 2、可变位置实参以字典方式接收值
def fn2(**kwargs):
print(kwargs) # {'name': 'Owen', 'age': 18}
# 第一种传参
fn2(name='Owen', age=18)
# 第二种传参
d = {'name': 'Owen', 'age': 18} # 单列集合及字符串类型都可以
fn2(**d)
- 函数对象:函数名
# 函数名就是存放了函数的内存地址,存放了内存地址的变量都是对象,即 函数名 就是 函数对象
# 函数对象的应用场景
# 1 可以直接被引用
# 2 可以当作函数参数传递
# 3 可以作为函数的返回值
# 4 可以作为容器类型的元素
- 名称空间与作用域: LEGB
# 名称空间:存放名字与内存空间地址对应关系的容器
# 作用:解决由于名字有限,导致名字重复发送冲突的问题
# 三种名称空间
# Built-in:内置名称空间;系统级,一个;随解释器执行而产生,解释器停止而销毁
# Global:全局名称空间;文件级,多个;随所属文件加载而产生,文件运行完毕而销毁
# Local:局部名称空间;函数级,多个;随所属函数执行而产生,函数执行完毕而销毁
# 注:
# del 名字:可以移除查找最近的名字与内存空间地址的对应关系
# 加载顺序:Built-in > Global > Local
函数作用域
# 作用域:名字起作用的范围
# 作业:解决同名字可以共存问题
# 四种作用域
# Built-in:内置作用域
# Global:全局作用域
# Enclosing:嵌套作用域
# Local:局部作用域
# 注:
# 不同作用域之间名字不冲突,以达到名字的重用
# 查找顺序:Local > Enclosing > Global > Built-in
- 闭包: 函数的嵌套定义
# closure:被包裹的函数,称之为闭包
# 完整的闭包结构:1.将函数进行闭包处理;2.提升函数名的作用域
# 案例:延迟加载
def get_site(url): #url='https://www.baidu.com'
def site():
response=requests.get(url)
if response.status_code == 200:
print(response.text)
return site
baidu=get_site('https://www.baidu.com')
python=get_site('https://www.python.org')
- 装饰器:闭包
装饰器:就是闭包(闭包的一个应用场景)
-- 把要被装饰的函数作为外层函数的参数通过闭包操作后返回一个替代版函数
优点:
-- 丰富了原有函数的功能
-- 提高了程序的可拓展性
#开放封闭原则
1.不能修改被装饰对象(函数)的源代码
2.不能更改被修饰对象(函数)的调用方式
#装饰器的简单实现
def outer(func):
def inner():
print("新增功能1")
func()
print("新增功能2")
return inner
def func():
print("原有功能")
func = outer(func)
#装饰器语法糖
def outer(func):
def inner():
print("新增功能1")
func()
print("新增功能2")
return inner
@outer
def func():
print("原有功能")
带参装饰器
# 为什么要出现带参装饰器
def outer(func):
# outer与inner之间要使用外部数据
# 可以解决的方案路径,给outer添加参数,但是outer的参数是固定一个,就是被装饰的函数
def inner(*args, **kwargs):
res = func(*args, **kwargs)
return res
return inner
# 所以只能使用函数的闭包,通过外层函数给内存函数传递参数的方式
def wrap(*arg, **kwargs):
def outer(func):
# 就可以使用wrap中的*arg, **kwargs,就是要使用的外部数据
def inner(*args, **kwargs):
res = func(*args, **kwargs)
return res
return inner
return outer
a = 10
b = 20
@wrap(a, b) # @wrap(10, 20) => @outer => fn = outer(fn) => fn = inner
def fn():
pass
wraps修改函数文档注释
# 为什么要出现该语法
from functools import wraps
def outer(func):
@wraps(func)
def inner(*args, **kwargs):
res = func(*args, **kwargs)
return res
return inner
def fn():
'''
fn的文档注释
'''
print(fn.__doc__) # fn本质是inner,使用打印fn.__doc__本质是inner函数的文档注释
# 形参假象:让打印fn.__doc__显示的效果是fn自己的