文章目录
函数
基础
参数、返回值均可为任意参数
def name(param1, param2, ..., paramN):
"""文档字符串"""
statements
return/yield value
和其他需要编译的语言(比如 C 语言)不一样的是,def 是可执行语句,这意味着函数直到被调用前,都是不存在的。当程序调用函数时,def 语句才会创建一个新的函数对象,并赋予其名字。
- 主程序调用函数时,必须保证这个函数此前已经定义过。
- 在函数内部调用其他函数,函数间哪个声明在前、哪个在后就无所谓,因为 def 是可执行语句,函数在调用之前都不存在。
闭包
1. 函数作为变量
def fun1(x):
print(x)
fun2 = fun1
fun2('abc')
2. 函数作为函数的参数:实参高阶函数
def fun1(x):
return x
def fun2(fun1, x):
print(fun1(x))
fun2(fun1, 'abc')
3. 函数中定义函数:嵌套函数
意义:
- 保证内部函数的隐私。
内部函数只能被所在的外部函数所调用和访问,不会暴露在全局作用域。- 函数开头需要做一些额外工作,而你又需要多次调用这个函数时,将那些额外工作的代码放在外部函数,就可以减少多次调用导致的不必要的开销,提高程序的运行效率。
def fun1():
def fun2(x):
return x
print(fun2('abc'))
fun1()
内部函数可以访问外部函数的变量,但要修改要加nonlocal
def fun1():
x = 'abc'
def fun2():
nonlocal x # 指定x为外部变量,而不是内部的局部变量
x = 'def'
fun2()
print(x)
fun1()
4. 函数的返回值为函数对象:返回值高阶函数
def fun1():
return fun2
def fun2(x):
print(x)
y = fun1()
y('abc')
闭包
闭包 = 函数嵌套 + 返回值高阶函数 + 函数变量(可选)
闭包常和装饰器一起使用
# 闭包
def fun1():
def fun2(x): # 函数嵌套
print(x)
return fun2 # 返回值高阶函数
y = fun1() # 函数变量:y=fun2
y('abc')
参数
值传递 和 引用传递
值传递:拷贝参数的值,然后传递给函数里的新变量。原变量和新变量之间互相独立,互不影响。
引用传递:原变量和新变量就会指向同一块内存地址
Python 中的参数传递只是让新变量与原变量指向相同的对象而已,并不存在值传递或是引用传递一说。
def fun(a):
a = 2
b = 1
fun(b) # b 和 a 都指向对象:1
参数为任何数据类型:
- 不可变对象:不会更改原变量
- 可变对象: 会永久性修改原变量
def fun1(li):
li.append(4)
def fun2(d):
d['a'] = 10
# 参数为list、dict
li= [1, 2, 3]
fun1(li) # 永久性修改原list
print(li) # [1, 2, 3, 4]
fun1(li[:]) # 传递副本,不修改原list
print(li) # [1, 2, 3]
d = {'a': 1, 'b': 2}
fun2(d) # 永久性修改原来dict
print(li) # {'a': 10, 'b': 2}
位置参数、关键字参数
位置参数:实参和形参位置顺序一致,一 一对应
关键字参数:无关顺序,需带关键字
def fun(x, y, z=0):
pass
# 位置实参
fun(1, 2)
fun(1, 2, 3)
# 关键字实参
fun(y=2, x=1)
fun(y=2, z=3, x=1)
5种参数类型 及 匹配顺序
- 关键字参数
- 位置参数
- 默认值参数:关键字 / 位置,等号两边不要有空格
- 任意数量的位置参数(*args:空tuple)
- 任意数量的关键字参数(**kwargs:空dist)
关于实形参的匹配顺序,满足以下原则:
- 非默认值参数 --> 默认值参数
- 位置参数 --> *args
- 关键字参数 --> **kwargs
- 位置参数 --> 关键字参数
- *args --> **kwargs
- *args --> 默认值位置参数
- 默认值关键字参数 --> **kwargs
关于顺序,只需要记住一个特例:fun(a, b, *args, c=None, kwa, kwb, kwc=None, **kwargs)
a、b、args、c为位置参数,kwa、kwb、kwc、kwargs为关键字参数
所有参数类型的匹配情况
# 位置参数
def func1(a, b, *args, c=None):
# 默认值参数和*args同时出现:*args --> 默认值参数,且必须将默认值参数转为关键字参数
print('---func1------------')
print(a)
print(b)
print(c)
print(args)
func1('a', 'b', 1, 2, 3, c='c')
func1('a', 'b', 1, 2, 3)
# 关键字参数
def func2(kwa, kwb, kwc=None, **kwargs):
print('---func2------------')
print(kwa)
print(kwb)
print(kwc)
print(kwargs)
func2(kwa='kwa', kwb='kwb', kwargs1=1, kwargs2=2)
func2(kwa='kwa', kwb='kwb', kwc='kwc', kwargs1=1, kwargs2=2)
# 位置参数和关键字参数
def func3(a, b, kwa, kwb):
print('---func3------------')
print(a)
print(b)
print(kwa)
print(kwb)
func3('a', 'b', kwa='kwa', kwb='kwb')
# *args 和 **kwargs
def func4(*args, **kwargs):
print('---func4------------')
print(args)
print(kwargs)
func4(1, 2, 3, kwargs1=1, kwargs2=2)
# 位置参数和关键字参数
def func5(a, b, *args, kwa, kwb, **kwargs):
print('---func5------------')
print(a)
print(b)
print(args)
print(kwa)
print(kwb)
print(kwargs)
func5('a', 'b', 1, 2, 3, kwa='kwa', kwb='kwb', kwargs1=1, kwargs2=2)
# 位置参数和关键字参数
def func6(a, b, *args, c=None, kwa, kwb, kwc=None, **kwargs):
print('---func6------------')
print(a)
print(b)
print(c)
print(args)
print(kwa)
print(kwb)
print(kwc)
print(kwargs)
func6('a', 'b', 1, 2, 3, c='c', kwa='kwa', kwb='kwb', kwc='kwc', kwargs1=1, kwargs2=2)
func6('a', 'b', 1, 2, 3, kwa='kwa', kwb='kwb', kwargs1=1, kwargs2=2)
匿名函数 lambda
减少代码的复杂度
定义、举例
定义:
lambda argument1, argument2,... argumentN : expression
举例:
fun = lambda: print('abc')
fun()
fun = lambda x: x**2
print(fun(3)) # 9
fun = lambda x1, x2: x1+x2
print(fun(1,2)) # 3
# 用于列表内部
li = [(lambda y: y+1)(x) for x in range(10)]
print(li) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 作为函数的参数
li = [(1, 20), (3, 0), (9, 10), (2, -1)]
li.sort(key=lambda x: x[1]) # 按列表中元组的第二个元素排序
print(li) # [(2, -1), (3, 0), (9, 10), (1, 20)]
# 结合 map()、filter()、reduce()
li = [1,2,3,4]
mp = map(lambda x:x**2, li)
for x in mp:
print(x)
li = range(10)
f = filter(lambda x: x%2==0, li) # 偶数
for x in f:
print(x) # [0,2,4,6,8]
from functools import reduce # python 3 取消了reduce内置函数
r = range(10)
result = reduce(lambda x,y: x+y, r) # 求和
print(result) # 45
lambda 和常规函数 def 的区别
lambda | def | |
---|---|---|
设计意义 | 只一行的简单表达式 | 多行语句 |
只调用一次 | 多次调用,减少代码重复性 | |
专注于简单的任务 | 更复杂的多行逻辑 | |
其它 | 无函数名 | |
可用于列表内部 | ||
可作为函数参数 |
表达式:运算符和操作数所构成的序列。如,x+1,1
语句:执行特定操作。如,x=x+1,x=1