引言
将一段代码集中到一块,起一个名字,下次可以根据这个名字再次使用这个代码块。
作用:
方便代码重用
分解任务,简化程序逻辑
使代码更加模块化
函数的参数
所有的传参方式都是传引用,注意列表做参数和数值做参数容易出现的问题。
单个参数
多个参数
定义方式
def funName(arg1, arg2, arg3...):
pass
调用方法
funName(arg1, arg2, arg3...) # 形参和实参一一对应
funName(arg2=v2, arg3=v3, arg1=v1) # 指明形参的名称,不用严格按照形参顺序
不定长参数
1. 利用元组的拆包装包
def mySum(args):
print(type(args)) # <class ‘tuple‘>
print(args) # (1, 2, 3, 4)
print(args) # 拆包操作 1, 2, 3, 4
for v in args:
todo ...
"""
装包,将传入的参数装入一个元组中,args就成了一个元组对象
拆包,将一个元组中的元素拆分出来,*args就成了参数序列
"""
2. 利用字典的键值对
def myInfo(**args):
print(type(args)) # <class ‘dict‘>
todo ...
myInfo(name="MetaTian", age=21)
默认参数
"""
调用某些函数时,可以省略某些参数,采用定义函数时指定的值
若不省略,则以调用时传入的值为准
"""
def sorted(iterable, reverse=False):
pass
new_list = sorted([1, 3, 2, 5])
new_list = sorted([1, 3, 2, 5], True)
返回值
返回语句标志着函数的结束,一个函数最好只有一处返回语句
如果想返回多个数据,可以把数据包装成一个集合,整体返回(列表,元组,字典...)
def funName():
data = {}
todo...
return data
偏函数
对于一个默认值较多的函数,有时我们需要重复用到其中的部分默认值,每次指定默认值比较麻烦。
可以将其中的默认值先赋值好,然后封装成一个新的函数,这就是偏函数。
import functools
numStr = "100010"
res = int(numStr, base=2)
print(res) # 34
int2 = functools.partial(int, base=2) # 重新封装,构成偏函数
print(int2(numStr)) # 34
高阶函数
一个函数的参数可以是另外一个函数
def calculate(a, b, cal_fun):
print(cal_fun(a, b))
def sum(a, b):
return a + b
def sub(a, b):
return a - b
calculate(2, 3, sum) # 5
calculate(2, 3, sub) # -1
匿名函数
lambda表达式
没有名字的函数
"""
lambda arguments: expression
冒号前面是参数,后面是要返回的表达式
"""
res = (lambda x, y : x + y)(1, 2)
print(res) # 3
fun = lambda x, y : x + y
print(fun(2, 3)) # 5
更多的是配合 map(), reduce()等函数进行使用
闭包
在函数嵌套定义的前提下
内层函数引用了外层函数的变量
外层函数把内层函数当做返回值
def line_config(content, length):
define line():
print(content * length)
return line
line1 = line_config("-", 5);
line2 = line_config("*", 6)
line1(); # -----
line2(); # **
作用域问题:内层函数要修改外层函数的变量,要使用nonlocal进行声明,否则变量属于内层函数。
def test():
num = 10
def test2():
nonlocal num # test中的 num被修改
num = 666
return test2
当内层函数使用外层的变化量时,注意值的情况
def test():
funs = []
for i in range(1, 4):
def test2():
print(i)
funs.append(test2)
return funs
"""
函数在运行时才会去确定变量的值
运行时,索引 i 的值因定义时迭代完成,不再发生变化
细节请参考迭代器部分
"""
myFuns = test()
myFuns[0]() # 3
myFuns[1]() # 3
myFuns[2]() # 3
装饰器
在调用目标函数之前,对这个函数对象进行装饰(增加一些其他功能)。
函数的名字不能改变。
函数体内部的代码不能发生改变。
使用案例
def check(func):
def inner():
print("登录验证...")
func()
return inner()
在 fss()和 ftp()执行之前,都会送入 check()进行包装
@check # 只要python解释器执行到了这行代码就会进行装饰执行
def fss():
print("发说说")
上面三行等价于 fss = check(fss)
@check
def ftp():
print("发图片")
上面三行等价于 ftp = check(ftp)
主业务逻辑如下:
flag = 1
if flag == 1:
fss() # 登录验证...
else: # 发说说
ftp()
多个装饰器的调用顺序
def one(func):
print(‘----1----‘)
def two():
print(‘----2----‘)
func()
return two
def a(func):
print(‘----a----‘)
def b():
print(‘----b----‘)
func()
return bpython入门系列:函数
原文地址:http://blog.51cto.com/14186420/2349767