函数参数
位置参数
一般写的函数调用按顺序传入参数,这种参数就是位置参数,即通过位置来知道这个参数是传给哪个参数的。
pow(x,n)
默认参数
即为参数设定默认值,具有默认值的参数可以不传入,所以必选参数在前,默认参数在后。
廖老师提到"变化大的参数放前面,变化小的参数放后面",但我觉得还是要视函数各个参数的实际意义和语义来考虑。
pow(x,n=2)
默认参数必须指向不变对象,因为默认参数的值在函数定义时就设定好了,如果改变了默认参数所指向的对象的内容,下次再调用时默认参数就是改变之后的了。
廖老师的例子中使用[]
空列表作为默认参数,在添加元素后这个对象就改变了,后来改成不变对象None
并在使用前判断是否是None
,如果是(表明使用了默认参数)再去使用空列表即可。
可变参数
符号*
放在函数形式参数前表示使用了可变参数,即可以传入任意个参数;放在列表或者元组前表示序列解包,可以用这种方式将其元素依次传入可变参数中。
def cal_sum(base, *num):
s = 0
for n in num:
s += n * base
return s
print(cal_sum(2, 2, 3)) # base=2,num=(2,3),结果是10
a = [2, 2, 3, 4]
print(cal_sum(*a)) # 序列解包再传入.base=2,num=(2,3,4),结果是18
关键字参数
可变参数将传入的任意多个普通参数组织成tuple
,而关键字参数将传入的任意多个k-v参数对组织成dict
,关键字参数在函数的形参前使用**
来指示。
def fun(c1, c2, **c):
print('c1:', c1, ',c2:', c2, ',c:', c)
fun(1, 2, c3=3, c4=4, c5=5) # c1: 1 ,c2: 2 ,c: {'c3': 3, 'c4': 4, 'c5': 5}
命名关键字参数
前面的关键字参数可以传入任意多的任意的合法的k-v对,使用命名关键字参数可以限制哪些关键字是要传入的。
命名关键字参数放在参数表靠后的位置,但在关键字参数之前,与之前的参数用一个*
参数隔开。
def fun(c1, c2, *, c3, c4, c5):
print('c1:', c1, ',c2:', c2, ',c3:', c3, ',c4:', c4, ',c5', c5)
fun(1, 2, c3=3, c4=4, c5=5) # c1: 1 ,c2: 2 ,c3: 3 ,c4: 4 ,c5 5
参数定义的顺序
必选参数、默认参数、可变参数、命名关键字参数、关键字参数。
闭包
在函数内部可以定义函数,并将其返回,以实现惰性求值的特性。当内部函数被保存到外部时就形成了闭包。
def createCounter():
a = 0
def counter():
nonlocal a # 指示a不是本地的,要到内部函数之外去找
a += 1
return a
return counter
if __name__ == '__main__':
counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
廖老师也没说闭包有什么用,反正就给了一个引用循环变量的例子,可变的变量在内部函数里反复返回之后,最后调用时全都是最终的那个值,可以再加一个中间的函数,专门用来传当前的值。
lambda函数
匿名函数,方便使用,也可以通过赋值到变量上来配备函数名。
print(list(map(lambda x: x / 2, [1, 2, 3, 4]))) # [0.5, 1.0, 1.5, 2.0]
装饰器
装饰器(Decorator)有点像Java注解配置切面一样,可以拿来打日志之类的,自定义一个函数,内部函数名为wrapper
并在里面调用要修饰的函数即可。
# 定义一个打日志的装饰器
def logger(fun):
def wrapper(*args, **kwargs): # 适应多参数
print("函数", fun.__name__, "启动前")
fun(*args, **kwargs) # 调用要修饰的函数
print("函数", fun.__name__, "启动后")
return wrapper
@logger # 把装饰器挂在要修饰的函数上
def sayHi():
print("Hi~")
sayHi()
输出:
函数 sayHi 启动前
Hi~
函数 sayHi 启动后
偏函数
用functools.partial
定义一个偏函数,即将函数的某些参数固定住,返回一个新的函数,为其命名以方便使用。
import functools
int2 = functools.partial(int, base=2)
print(int2('1110')) # 使用刚定义的偏函数
print(int('1110', base=2)) # 等价于这个,结果都是14