函数:功能模块,有利于代码重用、程序调试等。
Python提供了很多内置的函数,比如len等等,另外也可以自定义函数。
自定义函数
语法:
def 函数名([参数列表]): #参数列表可选项
函数体
函数 关键词 def ,后接函数名称和 圆括号()。任何传入参数和自变量必须放在圆括号中间,后跟冒号。函数体以缩进作为嵌套标识。
注意点:
- 圆括号内是形式参数列表,有多个参数则使用逗号隔开
- 形式参数不需要声明类型,也不需要指定函数返回值类型
- 无参数,也必须保留空的圆括号
- 实参列表必须与形参列表一一对应 (函数调用中实参与形参关系
- 没有函数类型,但是可以指定函数的返回值,通过 return 进行返回
- 先定义后调用。其他py文件中定义的函数,可以通过import 来完成导入。
函数调用,实参与形参
1、 函数调用构成中实参与形参要进行赋值处理,这里的赋值属于“浅拷贝”。
2、多个实参形参匹配可以通过 “顺序匹配” 也可以 “关键字” 匹配:
def t1(x,y):
print(x,y)
t1(y=5,x=6) # 指定 x=6 y=5
3、形参可设置默认值,规则与C/C++类似:一旦指定 某个形参的默认值,后面的所有形参都得给默认值
def t1(x,y=5): # def t1(x=6,y): 是错误的,x有默认值,后面的y必须也要默认值
print(x,y)
t1(x=6) # 与t1(6)等价
t1(6,7) # 指定值覆盖默认值
4、可以设置函数为不定长的参数,分两种情况:*param(一个星号),将多个参数收集到一个“元组”对象中。**param(两个星号),将多个参数收集到一个“字典”对象中。
def f1(a,b,*c):
print(a,b,c)
f1(8,9,19,20)
def f2(a,b,**c):
print(a,b,c)
f2(8, 9, name='Tom', age=18)
输出结果:
5、强制关键字调用函数, 在带星号的“可变参数”后面还有新的参数,必须在调用的时候“强制使用关键字参数调用”。
def f1(*a,b,c):
print(a,b,c)
#f1(2,3,4) #会报错。由于a是可变参数,将2,3,4全部收集。造成b和c没有赋值。
f1(2,b=3,c=4)
6、python不提供函数重载。(重载是同名不同参的函数),函数的参数传递是一种“浅拷贝”,那么函数调用的时候,可能会对实参产生影响。另外,字符串、元组等不能修改值的类型作为实参调用函数也要注意在函数中不能修改它们的值。
迭代器与生成器
迭代器是一个可以记住遍历的位置的对象。 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。 迭代器只能往前不会后退(只能遍历一次)。 迭代器有两个基本的方法:iter() 和 next()。 字符串,列表或元组,集合对象都可用于创建迭代器:
list=[1,2,3,4]
it = iter(list) # 创建迭代器对象
print (next(it)) # 输出迭代器的下一个元素 1
print (next(it)) # 2
生成器:使用了 yield 的函数被称为生成器。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
def f():
print('start')
a = yield 1
print(a)
print('middle....')
b = yield 2 # 2这个值只是迭代值,调用next时候返回的值
print(b)
print('next')
c = yield 3
print(c)
简单可以这样理解:第一次调用执行最开始的代码到第一个yield 后面如果跟了值,则该函数还返回后面的值(这里是 1) ;第二次调用则继续从第一次调用返回的地方继续执行。调用前当然需要先获取生成器:
a = f()
第一次调用:
print(next(a)) #输出 start 和 1 ,因为 yield 返回 1,即next(a) 的值为 1
第二次调用,从给b赋值开始,yield 已经发回,但是没有给 a 赋值 ,这行代码只执行了一半。
第二次调用需要给a赋值,可以采用:a.send('msg') 来实现。测试代码如下:
a = f()
print(next(a)) # 输出 start 和 1
a.send('msg') #因为函数调用中有print(a) ,所以输出 msg 再输出 middle....
print(a.send('msg1')) # b赋值为msg1 ,所以输出msg1 输出 next 并且打印返回值3
a.send('msg2') # c赋值为msg2,输出msg2
运行结果: