# 函数
# 定义函数
一个任务:把每个值乘 2 次方并除以 5 再加一
你可以这样做:
a = 10 | |
a = a**2/5+1 | |
print(a) |
但假如你要在不同的地方做 x 次操作呢?
就可以用到函数了:
def demo(num): | |
return num ** 2 / 5 + 1 | |
a = demo(10) | |
print(a) |
以下是函数的语法:
def 函数名(形参): | |
代码 |
return
后面是函数的返回值,需要使用变量 "接住"
在遇到 return
关键字之后,函数会自动退出
return 不是必须的,没有 return 则会在函数执行完后退出
# 参数
参数分为形参和实参,定义时的叫形参,填入的是实参
# 标准参数和类型标注
def demo(num:int|float) -> float: | |
return num+1 |
num
是标准参数,不填会报错: TypeError: demo() missing 1 required positional argument: 'num'
表示多个类型,则有多种标注方法:
- 3.9 版本以上:
int|float
,|
符号代表 A 类型或 B 类型 - Union [int, float], 需要先导入
typing
模块
-> float
表示返回值是float
类型,方便 IDE 分析
类型标注和返回值标注不是必须的,但建议使用
# 缺省形参和特殊参数
def demo(num: int | float = 10) -> float: | |
return num ** 2 / 5 + 1 | |
a = demo() | |
print(a) |
num: int | float = 10
中的 = 10
表示缺省
如果没有填入参数就使用 10 作为参数输入
def demo(*args): | |
for i in args: | |
print(i) | |
demo(1,2,3) |
这个函数会将传入的所有元素输出
*args
表示不知道会输入多少个元素,把所有参数做成元组处理
def demo(**kwargs): | |
for k,v in kwargs.items(): | |
print(k,v) | |
demo(k1=10,k2=12) |
**kwargs
代表把传入的参数作为字典处理,因此传入必须使用 键=值
这种方法
看不懂 **kwargs.items()
是什么意思就去复习一下字典
# 函数名
函数名和变量的命名规则很像,但可以使用小驼峰命名法:
例:numOutput
首字母小写,剩下的单词开头大写
# 作用域
python 的作用域分为以下几种:
Local 局部作用域,简写为 L
Enclosing 闭包作用域,简写为 E
Global 全局作用域,简写为 G
Built-in 内置作用域,简写为 B
变量和函数的搜寻的顺序:L->E->G->B
gvar = 0 # 全局作用域 | |
def demo(): | |
evar = 1 # 对于 demo2 的闭包作用域,对于 demo 的局部作用域 | |
def demo2(): | |
lvar = 2 #局部作用域 |
在作用域外不能调用作用域内的变量与函数
gvar = 0 # 全局作用域 | |
def demo(): | |
evar = 1 # 对于 demo2 的闭包作用域,对于 demo 的局部作用域 | |
def demo2(): | |
lvar = 2 #局部作用域 | |
demo2() | |
# NameError: name 'demo2' is not defined. Did you mean: 'demo'? |
把 demo2 套在 demo 里就叫闭包函数
加入作用域内有同名变量或更改变量值,需要使用 global
和 nonlocal
声明变量
语法: nonlocal/global 变量
global 是全局变量,nonlocal 是闭包变量
# typing 模块
typing 模块是 python 内置的类型表示模块,对于函数类型标注非常有帮助
# 可迭代容器数据
举个例子,这个函数可以遍历可迭代容器数据并输出:
def printSeq(seq: list): | |
for i in seq: | |
print(i) |
最开始使用 list 进行类型标注,但假如要使用元祖,python 就会报错。
而且如果只是单纯加上元祖,后续出现新的类型还需要改代码
这个时候就可以用到 list 的抽象类 typing.Sequence
def printSeq(seq: typing.Sequence): | |
for i in seq: | |
print(i) |
就可以实现接受所有的可迭代容器数据
# 可能为 None 的参数
在实际开发中,部分参数需要传入 None 来实现功能,虽然可以用 |
或 Union
来解决,但有更优雅的方法:
def numAbs(n: int, mode: typing.Optional[bool]): | |
if mode is None: | |
return 0 | |
else: | |
return abs(n) |
typing.Optional
与 Union
是等价的,只是前者默认包含 None
typing 包含有大量抽象类供类型标注,可以查看官方文档
typing 中部分内置类 (区别为首字母大写) 不要使用,请使用标准的内置类
这些冗余的类会在 python3.9 发行五年后的第一个版本移除