函数
简介
函数是一些列代码的集合,用来完成某项特定的功能
优点
1、避免代码冗余
2、让程序代码结构更加清晰
3、代码具有复用性,便于维护
函数的四部分
1、函数名:使用该函数的依据
2、函数体:完成功能的代码块
3、参数:完成功能所需要的条件
4、返回值:完功能完成的反馈结果
函数的定义与调用的完整语法
# 1、定义
# def 是声明函数的关键字,后面跟着函数名,括号内是函数的参数
def 函数名(参数1,参数2,参数3,...):
'''注释'''
函数体 # 函数体写具体的逻辑代码
return 返回的值 # retrun后面是函数的返回值,是函数体代码的运行成果
# 2、调用
函数名(参数1,参数2,参数3,...)
'''注:
-- 先定义再调用
-- 函数名存放的是函数地址
-- ()会触发函数体的执行
-- 函数执行完毕得到的是函数的返回结果,通常称之为函数的返回值,也称函数值
函数详解
根据函数体划分
- 空函数:用来罗列功能
# 空函数值的是函数体用的是pass占位,pass代表什么也不做
def func():
pass
# func():调用后什么事都干不了
- 非空函数:正常可以完成某项功能
def func():
print('非空函数')
# func():调用后执行函数体
根据参数列表划分
- 无参函数:不需要外界资源
def start():
print('系统启动')
start()
- 有参数:需要外界资源
def login(usr,pwd):
if usr == 'mak' adn pwd == '123':
print('登陆成功')
else:
print('登陆失败')
login('mak','123')
根据返回值划分:return是用来结束函数的
- 空返回:返回None
def demo(x,y):
print(x+y)
def demo(x,y):
print(x+y)
return
## 注意函数如果没写return则默认是 return None 同样写return 也是默认返回 None
- 一值返回
def demo(x,y):
return x+y
- 多值返回
def demo(x,y):
return x+y,x-y,x*y
## 本质就是返回一个装有多个值的元组,写的时候注意用逗号隔开
函数的嵌套调用
# 求两个数最大值
def max_2(n1, n2):
if n1 > n2:
return n1
return n2
# 求三个
def max_3(n1, n2, n3):
m2 = max_2(n1, n2)
return max_2(m2, n3)
# 求四个
def max_4(n1, n2, n3, n4):
m2 = max_2(n1, n2)
return max_3(m2, n3, n4)
# 循环调用:在一个函数的内部调用另一个函数
形参与实参
def fn(形参们)
pass
fn(实参们)
# 形参:定义函数,在括号内声明的变量名,用来接收外界传来的值
# 实参:调用函数,在括号内传入的实际值,值可以为常量变量,表达式或者三者的组合
# 注:形参随着函数的调用而产生,随着调用的结束而销毁(有特例)
实参的分类
'''
位置实参:必须按照顺序给形参传值
关键字实参:按照关键字给形参传值,所以顺序可以颠倒
# 注:位置实参、关键字实参共存时,关键字参数必须在位置参数之后
'''
形参的分类
'''
位置形参:位置实参与关键字实参都可以对其传参
默认形参:位置实参与关键字实参都可以对其传参
可变长位置形参:接收位置形参、默认形参没有接受完的所有位置实参
无初值关键字形参:只能由关键字实参传值
有初值关键字形参:只能由关键字实参传值,也可以不被传值
可变长关键字形参:接收两种关键字形参没有接收完的所有关键字实参
# 注:各种形参出现的先后
位置形参 - 默认形参 - 可变长位置形参 - 无|有初值关键字形参 - 可变长关键字形参
'''
def fn(a, b, c=10, *args, d, e=20,f,**kwargs):
pass
# 位置形参:a , b
# 默认形参:c
# 可变长位置形参:args
# 无初值关键字形参:d
# 有初值关键字形参:e
# 可变长关键字形参:kwargs
## 注意:当位置参数后出现*或者*args那么后面的都是关键字参数了
函数对象
# 函数名就是存放了函数的内存地址,存放了内存地址的变量都是对象,即 函数名就是函数对象
# 函数对应的原因
# 1、可以直接被引用
# 2、可以当做函数参数传递
# 3、可以作为函数的返回值
# 4、可以作为容器类型的元素
名称空间
# 名称空间:存放名字与内存地址对应关系的容器
# 作用:解决由于名字有限,导致名字重复发生冲突的问题
# 三种名称空间
# 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')
## 现在得到的baidu和python都是函数对象,之后加上括号就可以直接调用了
装饰器
装饰器:就是闭包(闭包的一个应用场景)
-- 把要被装饰的函数作为外层函数的参数通过闭包操作后返回一个代替版函数
优点:
--丰富原有函数的功能
--提高了程序的拓展性
开放封闭原则
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 # 这句话等价于 func = outer(func) = inner
def func():
print('原有功能')
装饰器有参有返的函数
def outer(func):
def inner(*args,**kwargs):
print('新加功能1')
result = func(*args,**kwargs)
print('新加功能2')
return result
return inner
@outer # 等价于 func = outer(func) = inner
def func(*args,**kwargs):
print('原有功能')
return '原有结果'
# 有参有返的标准写法
有参数装饰器
def wrap(arg)
def outer(func):
def inner(*args,**kwargs):
print('新加功能1')
result = func(*args,**kwargs)
print('新加功能2')
return result
return inner
@wrap('装饰器参数') #等价于 func = warp('装饰器参数') = inner
def func(*args,**kwargs):
print('原有功能')
return '原有结果'
wraps修改函数文档注释
from functools import wraps
def outer(func):
def inner(*args,**kwargs):
'''装饰器文档注释'''
func(*args,**kwargs)
return inner
def func(*args,**kwargs):
'''原文档注释'''
print('原有功能')
迭代器
# 迭代器:循环反馈的容器(集合类型)
# -- 不同于索引取值,但也可以循环的从容器对象中从前往后逐个返回内部的值
# 优点:不依赖索引,完成取值
# 缺点:不能计算长度,不能指定位取值(只能从前往后逐一取值)
可迭代对象
# 可迭代对象:内置有__iter__()方法的对象,称之为可迭代对象
# 可迭代对象:str | list | tuple | dict | set | range() | file | 迭代器对象 | enumerate() | 生成器
迭代器对象
'''
迭代器对象:有__next__()方法的对象,也就是用该方法一次从迭代器对象中获取一个值,且取出一个少一个
有哪些:file | enumerate() | 生成器
重点:
1、从迭代器对象中取元素,取一个少一个,如果要从头开始取,需要重新获得拥有所有元素的迭代器对象
2、迭代器对象也有__iter__()方法,调用后得到的是自己本身(当前含几个元素得到的就是含几个元素的迭代器)
'''
for循环迭代
'''
1、自动获取被迭代对象的迭代器
2、在内部一次一次调用__next__()方法取值
3、自动完成异常处理
'''
生成器
# 生成器:包含yeild关键字的函数就是生成器
def my_generator():
yield 1
yield 2
yield 3
g_obj = my_generator()
# my_generator()并不会执行函数体,得到的返回值就是生成器对象
# 生成器对象就是迭代器对象
r1 = g_obj.__next__() # 1
for v in g_obj:
print(v) # 2 | 3 1已经被取出了
三目运算符
# 三元运算符:就是 if ... else ...语法糖
#前提:简化if...ese...结构,且两个分支有且只有一条语句
#注:三元运算符的结果不一定要与条件直接性关系
cmd = input('cmd')
print('可以转化为数字') if cmd.isdigit() else print('不可以转化为数字')
a = 20
b = 30
res = a if a > b else b # 求最大值
print(res)
res = 'b为小值' if a > b else 'a为小值' # 求小值
print(res)
推导式
# 列表推导式:[v for v in iterable]
dic = {'a':1,'b':2,'c':3} # => [('a',1),('b',2),('c',3)]
res = [(k,v) for k,v in dic.items()]
# 字典推导式:{k:v for k, v in iterable}
ls = [('a', 1), ('b', 2), ('c', 3)] # => {'a': 1, 'b': 2, 'c': 3}
res = {k: v for k, v in ls}
递归
# ***
# 递归:回溯与递推
# 回溯:询问答案的过程
# 递推:推出答案的过程
# 本质:函数的自我调用
# 直接:自己调自己
# 间接:自己调别人,别人最终由调回自己
匿名函数
# 匿名函数:没有名字的函数
# 语法:lambda 参数列表:一个返回值表达式
#重点:
#1、匿名函数:没有函数名,没有函数体,只有一个返回值
#2、关键字:lambda | 参数列表省略() | 返回值return关键字也被省略
# 应用场景
# 1、匿名函数的地址可以被一个变量接收,该变量就可以作为函数名来使用,但就违背了匿名函数的初衷
# 2、结合内置函数来使用:内置函数某些参数需要一个函数地址,
# --可以赋值一个有名函数名,也可以直接赋值匿名函数
内置函数
https://docs.python.org/zh-cn/3.7/library/functions.html#all