一.函数的作用
1.减少重复代码
2.方便修改,易于扩展
3.保持代码一致性,增强可读性
二.函数的使用和结构
1.函数的创建:
def 函数名(<参数>):
函数体
2.函数的调用:函数名(<参数>)
3.函数的命名规则:和变量一样
4.函数和变量类似,故函数名也可以进行赋值,如f1=f2,则f2函数与f1函数功能一样
5.函数的参数:
(1)形参:
形式参数,不是实际存在,是虚拟变量。在定义函数和函数体的时候使用形参,目的是在函数调用时接收实参(实参个数,类型应与实参一一对应)
(2)实参:
实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给形参
(3)区别:
形参是虚拟的,不占用内存空间,.形参变量只有在被调用时才分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参
6.实例:
import time
times=time.strftime('%Y--%m--%d') #取出当前时间
def f(time):
print('Now time is : %s'%times) #利用格式化输出,将变化内容作为参数
f(times)
三.函数的参数
1.必备参数
(1)备注:必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
(2)示例:
def f(name,age):
print('Name:%s Age:%d' %(name,age))
f('zhou',20)
2.关键字参数
(1)备注:关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。
(2)示例:
def f(name,age):
print('Name:%s
Age:%d' %(name,age))
f(age=20,name='zhou')
3.默认参数
(1)备注:调用函数时,缺省参数的值如果没有传入,则被认为是默认值。一般放在其他参数的后面。
(2)示例:
def f(name,age,sex='male'):
print('Name:%s
Age:%d
Sex:%s' %(name,age,sex))
f('zhou',20)
f('lin',20,'female')
4.不定长参数
(1)备注:一个函数能处理比当初声明时更多的参数,这样的参数叫做不定长参数,和上述2种参数不同,声明时不会命名。
(2)示例1:(加法器)
def add(*args): #*代表参数不定长,且参数为元组形式
sum=0
for i in args:
sum+=i
print(sum)
add(1,2,3)
(3)示例2:(个人信息显示)
def f(*args,**kwargs): #**代表参数不定长,且参数为字典形式
print('Name:%s Age:%d Sex:%s' %(args[0],args[1],args[2]))
for i in kwargs:
print(%s:%s %(i,kwargs[i]))
f('zhou',20,'male',Hobby='invention',Job='student') #前三个没有键的存入args成为元组,后两个有键的存入kwargs成为字典
(4)示例3:(将一个列表/字典拆分传输)
def f(*args/**kwargs):
print(args/kwargs)
f(*[1,2,3]/**{'name':'zhou'}) #此时打印结果为1,2,3/{'name':'zhou'}单个元素而不是整个列表/字典
(5)参数优先级:关键参数>默认参数>*args>**kwargs,必须按照此顺序排列实参
四.函数的返回值
(1)要想获取函数的执行结果,就可以用return语句把结果返回
(2)函数在执行过程中只要遇到return语句,就会停止执行并返回结果,所以也可以理解为 return 语句代表着函数的结束
(3)如果未在函数中指定return,那这个函数的返回值为None
(4)return多个对象,解释器会把这多个对象组装成一个元组作为一个一个整体结果输出。
(5)函数返回值既可以是一个变量,也可以是一个函数,例如:
def f():
def inner():
return 6
return inner
f() #此时返回的是一个地址,即储存函数代码的地址
五.函数的作用域
1.作用域介绍
(1)L:local,局部作用域,即函数中定义的变量;
(2)E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;
(3)G:globa,全局变量,就是模块级别定义的变量;
(4)B:built-in,系统固定模块里面的变量,比如int, bytearray等。
(5)搜索变量的优先级顺序依次是:局部作用域>外层作用域>当前模块中的全局>python内置作用域,也就是LEGB(从小到大)。
(6)示例:
x = int(2.9) # int built-in
g_count = 0 # global
def outer():
o_count = 1 # enclosing
def inner():
i_count = 2 # local
2.作用域产生
在Python中,只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如if、try、for等)不会引入新的作用域
3.变量的修改
(1)局部作用域只能读取全局作用域的变量,但不能修改:(下面的程序会报错)
x=1
def a():
print(x)#此时拿到的是全局变量10
x=2 #错误的原因在于print(x)时,解释器会在局部作用域找,会找到x=2(函数已经加载到内存),但x使用在声明前了,所以报错
a()
(2)要想修改全局作用域中的变量,需在局部变量前加global
(3)要想修改嵌套作用域中的变量,需在局部变量前加nonlocal
六.高阶函数
1.高阶函数需要满足的条件(至少其中之一):
(1)接受一个或多个函数作为输入
(2)输出一个函数
2.示例:
def f(n):
return n*n
def F(a,b,func)
print(f(a)+f(b))
F(1,2,f) #输出5
七.递归函数
1.定义:在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
2.递归函数的优点:定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
3.递归特性:
(1)必须有一个明确的结束条件
(2)每次进入更深一层递归时,问题规模相比上次递归都应有所减少
(3)递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
八.内置函数
1.内置函数大全:https://docs.python.org/3.5/library/functions.html#repr
2.重要的内置函数:
(1)filter(function, sequence) #将sequence中的item一个一个传入function
示例:
str = ['a','b','c','d']
def fun1(s):
if s != 'a':
return s
ret = filter(fun1, str)
print(list(ret)) #ret是一个迭代器对象
解释:对sequence中的item依次执行function(item),将执行结果为True的item做成一个filter object的迭代器返回。可以看作是过滤函数。
(2)map(function, sequence)
示例1:
str = ['a','b','c']
def fun2(s):
return s+‘zhou’
ret = map(fun2, str)
print(list(ret)) #['azhou', 'bzhou', 'czhou']
解释:对sequence中的item依次执行function(item),将执行结果组成一个map object迭代器返回。
示例2:
ef add(x,y):
return x+y
print (list(map(add, range(10), range(10))))##[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
解释:map也支持多个sequence,这就要求function也支持相应数量的参数输入
(3)reduce(function, sequence, starting_value)
示例:
from functools import reduce
def add1(x,y):
return x + y #若为x*y则可以用来做阶乘
print (reduce(add1, range(1, 101))) # 5050 (注:1+2+...+99+100)
print (reduce(add1, range(1, 101), 20)) # 4970 (注:1+2+...+99+20)
解释:对sequence中的item顺序迭代调用function,如果有starting_value,还可以作为初始值调用。
(4)lambda #匿名函数
匿名函数的命名规则:
用lamdba 关键字标识,冒号(:)左侧表示函数接收的参数(a,b) ,冒号(:)右侧表示函数的返回值(a+b)。
普通函数与匿名函数的对比:
#普通函数
def add(a,b):
return a + b
print(add(2,3))
#匿名函数
add=lambda a,b : a + b, [2,3]
print(add(2,3)) #一行即可实现上面多行内容,用于代码简化
#输出
5
5
匿名函数使用范围:当函数名不重要而只用其内容时,可以用lambda将函数体直接引用,省去定义函数的代码
3.结合使用功能更加强大:
(1)阶乘:(reduce+lambda)
from functools import reduce
print (reduce(lambda x,y: x*y, range(1,6)))
(2)平方:(map+lambda)
squares = map(lambda x : x*x ,range(9))
print (squares) #<map object at 0x10115f7f0>迭代器
print (list(squares)) #[0, 1, 4, 9, 16, 25, 36, 49, 64]