函数概述
函数是组织好的、可重复使用的、用户实现单一或者关联功能的代码段。函数能够提高应用的模块性和代码的重复使用率。
函数的定义规则
- 函数代码块以def关键词开头,后接函数标识符名称和圆括号()
- 任何传入参数和自变量必须放在圆括号中间
- 函数的第一行语句可以选择性使用文档字符串——用于存放函数说明
- 函数内容以冒号起始,并且缩进。
格式
def 函数名([参数]):
#函数说明
要封装的代码段
调用函数
Python内置了很多函数,内置函数可以直接调用。调用一个函数需要知道函数的名称和函数的参数。
函数名其实就是指向一个函数对象的引用,完全可以把函数名赋值给一个变量,相当于给这个函数起了一个别名。
函数参数分类
- 必备参数
- 关键字参数
- 默认参数
- 不定长参数
必备参数
函数定义中允许拥有多个形参,因此函数在调用的时候,也可能包含多个实参。向函数传递参数的方式有很多,通过实参和形参的顺序对应,这就是位置实参。只有位置一致,才能被正确匹配。位置实参是最简单也最常用的关系方式。
参数的个数不能少,也不能多。参数的位置要一一对应,不能写错。
关键字参数
关键字实参是传递给函数的名称-值对。直接在实参中将名称和值关联起来,因此向函数传递实参时不会混淆。函数调用使用关键字参数来确定传入的值。使用关键字参数允许函数调用者的顺序与声明时不一致,因为Python解释器能够用参数名匹配参数值。
def getInfo(name,address)
print(’大家好我叫%s,我来自%s’%(name,address))
getInfo(address=’香港’,name=’刘德华’)
参数默认值
函数定义的时候,设置的参数是形参。那么也可以给每个形参指定一个默认值。当调用函数时如果没有传入实参,就使用形参的默认值。如果调用的时候传入实参,那么程序将使用传入的实参。
def getInfo(name, address=’香港’)#默认值参数,就是在声明参数的时候给形参赋值
getInfo(name=’刘德华’)#有默认值的形参,可以不用传递值
getInfo(address=’香港’,name=’刘德华’)#传递参数的话,会覆盖原来的默认值
不定长参数
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数。
def getInfo(name,address,*args,**args2)
#*args 是接收所有未命名的参数
#**args 是接收所有命名的参数
#args是一个元组
#args是字典数据类型
getInfo(’刘德华’,’九龙’,’a’,’b’,’c’,’d’,age=’18’)
可变对象与不可变对象的传递
在python中,strings,tuples和numbers是不可更改的对象,而list,dict,set等则是可变对象。
不可变对象
变量赋值a=5后再赋值a=10,这里实际是新生成一个int值对象10,再让a指向它,而5被丢弃,不是改变a的值,相当于新生成了a。
可变类型
变量赋值la=[1,2,3,4]后再赋值la[2]=5则是将list la的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。
区别
不可变对象,传递的是对象的值,不是对象本身。如果修改值,修改的是另一个复制的对象,不会影响原来对象的本身。
可变对象,传递对象自己。函数内部如果修改值会影响对象本身。
函数的返回值
什么是返回值
函数并非总是将结果直接输出,相反,函数的调用者需要函数提供一些通过函数处理过后的一个或者一组数据,只有调用者拥有了这个数据,才能够做一些其他的操作。那么这个时候,就需要函数返回给调用者数据,这个就称之为返回值。想要在函数中把结果返回给调用者,需要在函数中使用return。
return语句
return语句用于退出函数,选择性的向调用者返回一个表达式。直接return的语句返回None。
函数类型
- 无参数,无返回值的函数
- 无参数,有返回值的函数
- 有参数,无返回值的函数
- 有参数,有返回值的函数
什么是yield呢
Yield的作用就是把一个函数变成一个generator,带有yield的函数不再是一个普通函数,Python解释器会将其视为一个生成器,调用这个函数,不会执行该函数,而是返回一个iterable迭代(在当前的基础上到下一个结果)对象!
区别:与return类似,都可以返回值,但不一样的地方,yield可以返回多次值(后面的代码会继续运行),而return只能返回一次(后面的代码不会运行)。
def getNum(n):
i = 0
while i < = n
yield i#将函数变成一个generator对象
i+=1
生成器(generator)
使用了yield的函数被称为生成器。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次从当前位置继续执行。
a = getNum(5) #把生成器复制给一个变量a
#使用生成器 通过next()方法
print(next(a))
#通过for循环,使用生成器
for i in a:
print(i)
a = [x for x in range(10000000)]#这样生成一个列表会占用很多内存
a = (x for x in range(10000000)) #使用生成器可以达到延迟操作的效果,所谓延迟操作就是指在需要的时候产生结果,而不是立即产生结果,节省资源消耗,和声明一个序列不同的是,生成器在不使用的时候几乎是不占内存的。
#注意这里是生成器,不是元组推导式,没有元组推导式
print(next(a))
def gen()
i= 0
while I < 5:
temp = yield i #不是赋值操作
#使用了yield之后是一个生成器
print(temp)#是None 因为yield之后返回结果到调用者的地方,暂停运行,赋值操作没有运行。
i+=1
print(a.send(’我是a’)) #可以将值发送到上一次yield的地方
迭代器
迭代是Python最强大的功能之一,是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。
它可以被next()函数调用并不断返回下一个值。
迭代器只能往前不会后退。迭代器有两个基本的方法:iter()和next()。
字符串,列表或元组,集合对象都可以用于创建迭代器:
list=[1,2,3,4]
it = iter(list)#通过iter()将一个可迭代对象变成迭代器
print(next(it))#输出迭代器的下一个元素
什么是迭代对象
可以用for in 遍历的对象都可以叫做可迭代对象:Iterable
变量的作用域
一个程序的所有的变量并不是在哪个位置都可以访问的。访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序你可以访问哪个特定的变量名称。两种最基本的变量作用域如下:
- 全局变量
- 局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
可变类型的全局变量
- 对于不可变类型的全局变量来说,要在函数中修改需要global声明。
- 对于可变类型的全局变量来说,要在函数中修改可以不使用global声明。
a = 2
def test():
global a #将函数内部的变量声明为全局变量,但一般不这么使用
a= 3
print(a)
print(a)
递归函数
递归就是子程序(或函数)直接调用自己或通过一系列调用语句间接调用自己,是一种描述问题和解决问题的基本方法。(一句话,自己调用自己)
后进先出
def main(n):
print(’进入第%d层梦境’%n)
if n == 3:
print(’ 到达潜意识区,开始醒来’)
else:
main(n+1)
print(’从第%d层梦境醒来’%n)
第一次调用:进入第1层梦境
第二次调用:进入第2层梦境
第三次调用:进入第3层梦境 到达潜意识区,开始醒来
结束第三次调用:从第3层梦醒来
结束第二次调用:从第2层梦醒来
结束第一次调用:从第1层梦醒来
匿名函数
定义函数的过程中,没有给定名称的函数叫做匿名函数。Python中使用lambda表达式来创建匿名函数。
lambda来创建匿名函数规则。
- lambda只是一个表达式,函数体比def简单很多。
- lambda的主体是一个表达式,而不是一个代码块,所以不能写太多的逻辑进去。
- lambda函数拥有自己的命名空间,且不能访问自由参数列表之外或全局命名空间里的参数。
- lambda定义的函数的返回值就是表达式的返回值(默认),不需要return语句块
- lambda表达式的主要应用场景就是赋值给变量、作为参数传入其它函数
lambda匿名函数的表达式规则是:lambda参数列表:表达式
s = lambda : ’哈哈哈’ #t通过lambda声明一个匿名函数并赋值给变量s
print(s())#通过s调用匿名函数
#声明一个参数
s = lambda x: x*2 #lambda里面不能包含for循环等,只能是简易表达式
print(s(3))
#声明两个参数
s = lambda x,y :x+y#lambda不能换行,必须在一行中写完
print(s(3,2))
#矢量化的三元运算符
#条件成立的内容 if 条件 else 条件不成立的内容
S = lambda x,y: x if x > 2 else y
print(s(3,4))
内置函数与高阶函数
#字典排序
dic = {’a’:1,’c’:3,’b’:2}
#通过内置函数sorted进行排序
dic = sorted(dic.items(),key = lambda x:x[1],reverse=True)#内置函数有返回值 默认通过Key排序
print({k:v for k,v in dic})#字典推导式
#列表字典的排序
list = [
{’name’:’joe’,’age’:18},
{’name’:’susan’,’age’:19},
{’name’:’Tom’,’age’:17},
]
list = sorted(list,key = lambda x:x[’age’],reverse=True)
常用高阶函数
方法 | 描述 |
map(func,seq[,seq[,seq…]]) | 接收一个函数及多个集合序列,会根据提供的函数对指定序列做映射,然后返回一个新的map对象 |
filter(func,seq) | 用于过滤序列,过滤掉不符合条件的元素,返回符合条件元组组成的filter对象 |
reduce(func,seq[,initvalue]) | 对于序列中的所有元素调用func进行数据合并操作,可以给定一个初始值 |
#map
list=[1,2,3,4,5]
new_list = map(lambda x:x*2,list)
print(list(new_list))#将map对象转换为list [2,4,6,8,10]
list01=[1,3,5,7,9]
list02=[2,4,6,8,10]
new_list = map(lambda x,y:x*y,list01,list02)
print(list(new_list))# [2,12,30,56,90]
#filter
list = [2,4,6,8,10]
new_list = filter(lambda x:x>4,list)
print(list(new_list))
#reduce
from functools import reduce
list = [2,4,6,8,10]
new_list = reduce(lambda x,y:x+y,list,0)
print(new_list)#30
高阶函数实例
name = [’joe’,’susan’,’black’,’lili’]
age = [18,19,20,21]
sex = [’m’,’w’,’m’,’w’]
#格式化用户的英文名,要求首字母大写,其它字母小写
new_name = map(lambda x:x.title(),name)
new_name = list(new_name)
print(new_name)
#将用户英文名,年龄,性别三个集合的数据结合到一起,形成一个元组列表
users = maps(lambda x,y,z:(x,y,z),name,age,sex)
new_users = list(users)
print(new_users)
#过滤性别为男的用户
new_users = filter(lambda x:x[2] == ’m’,new_users)
new_users = list(new_users)
print(new_users)
#求性别为男的用户的平均年龄
total_age = reduce(lambda x,y:x+y[1], new_users,0)
print(total_age)
print(total_age/len(new_users))