文章目录
为了避免重复的写一段功能,将重复的功能写成一个函数,当需要的时候通过调用函数,从而达到节省代码的功能。
python中函数的定义关键字是:
def
定义一个函数
#定义一个空函数
def fun():
pass
其中pass是一个占位符,表示跳过,方便以后添加内容
函数的定义格式如下:
def 函数名(参数):
函数体(要执行的一段代码)
return (返回值)
return是一个表达式,表示函数的返回值
遇到了return表示函数执行完毕,写在ruturn后的代码,并且和return的缩进一直的代码不会被执行
使用函数的时候直接使用函数名即可调用函数。
#一个简单的相加函数
def add(a,b):
res = a+b
return res
#函数调用
result = add(4,5)
print(result)
#通过调用函数add得到4+5的结果,通过返回值保存到result变量中
带参数的函数
python中参数无类型,参数可以接受任意对象,只有函数代码才会对参数类型有限制。
函数的参数有三种:
- 必备参数
- 默认参数
- 不定长参数
def add(a,b):
res = a+b
return res
上述例子中a和b就是函数的参数。
必备参数
必备参数就是如果函数内有几个参数,就必须传入几个参数。
如下:
def add(a,b):
res = a+b
return res
#a和b都是必备参数,调用的时候两个参数都必须传递
result=add(4,5)
上述的add函数中,a和b就是必备参数。
默认参数
如果函数有了默认参数,调用函数的时候,可以只传入必备参数,而不必传默认参数。
默认参数需要在函数定义的时候就确定默认的参数值,但是如果调用的时候对默认参数也传递了参数,那么这个默认参数以调用函数的时候传入的参数为准。
如下:
def add(a,b,c=10):
res = (a+b)*c
return res
#a和b都是必备参数,而c则是默认参数
#函数调用的时候不传入默认参数
result=add(4,5)
print(result)
#结果为 90
#函数调用的时候传入默认参数,此时默认参数c的值为6
result=add(4,5,6)
print(result)
#结果为 54
不定长参数
不定长参数又分为可变参数和关键字参数;
可变参数
其中可变参数传入的参数个数是可变的,可变参数在函数调用时自动组装为一个元组(tuple)
在参数前面加一个**号*。
#可变参数
def add(*args):
sum=0
for i in args:
sum +=i
return sum
#函数调用传参
add(1,2,3,4,5,6)
如果传参的时候传入的本身是一个元组
tu = (1,2,3,4,5)
#那么调用时会有如下两种方式传参
#第一种
add(tu)
#这种传参的方式是将整个元组作为一个单独的参数传入函数
#此时函数需要如下才能正常调用参数
def add(args):
sum=0
for i in args:
sum +=i
return sum
#因为元组是一个整体,相当于一个参数,所以参数前不能加*号
#第二种
add(*tu)
#这种传递相当于把元组tu每个元素单独拆分后传入,所以可以直接调用add函数
即如果传入的参数本身是一个元组,
那么在传参时,不加*号,则整个元组作为单独的参数传入函数中;
如果加*号,则会将元组元素拆分后传入函数。
关键字参数
对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过kw检查,特殊分隔符后面的参数被视为命名关键字参数。一般在参数面前加两个*号。
#关键字参数
def getValue(**kwargs):
for i,value in enumerate(kwargs):
print('index:{},value:{}'.format(i,value))
#传参的时候需要如下方式传参
d1 = {'name':'瞎子','age':'18','sex':'男'}
getValue(**d1):
关键字参数在传递时,需要加上两个*号,如果不加,则只会把传入的参数整体作为一个参数,函数内部参数的调用可能出错。
内置函数
python中有一些内置函数:
例如 print()就是一个内置函数,执行控制台打印输出的功能。
这些内置函数都不是我们自己写的,在使用的时候直接使用。
通过内置对象
dir(__builtins__)
可以查看有多少内置函数,其中常见的内置函数如下:
函数名 | 说明 |
---|---|
print() | 控制台执行的打印 |
len() | 求对象长度 |
min() | 求最小值 |
max() | 求最大值 |
sorted() | 排序函数 |
reversed() | 反向排序函数 |
sum() | 求和函数 |
bin() | 转换为二进制函数 |
oct() | 转换为八进制函数 |
hex() | 转换为十六进制函数 |
ord() | ASCII码表编码查看 |
chr() | ASCII码表字符查看 |
enumerate() | 返回一个枚举对象 |
eval() | 取出字符串内容,将字符串当成有效表达式 |
exec() | 执行字符串或compie方法编译过的字符串 |
filter() | 过滤器 |
map() | 执行对应的func,返回的结果保存到map对象中 |
zip() | 可将字典和列表互转 |
部分内置函数使用示例
li = [5,2,6,8,7,15]
#求li的长度 结果6
len(li)
#求li中的最大值 结果15
max(li)
#求li中的最小值 结果2
min(li)
#对li进行排序 结果[2, 5, 6, 7, 8, 15]
sorted(li)
#反向排序 结果[15, 7, 8, 6, 2, 5]
list(reversed(li))
#对li元素求和 结果 43
sum(li)
#将数值转换为二进制 结果'0b1100'
bin(12)
#查看对应字符的ASCII码表编码 结果115
ord('s')
#查看ASCII码表对应编码的的字符 结果't'
chr(116)
enumerate()
返回一个枚举对象
li = ['a','b','c','d']
list(enumerate(li))
#结果[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
#或者返回一个字典
dict(enumerate(li))
#结果{0: 'a', 1: 'b', 2: 'c', 3: 'd'}
#利用循环获取枚举对象
for i,value in enumerate(li):
print('index:{},value:{}'.format(i,value))
#结果
"""
index:0,value:a
index:1,value:b
index:2,value:c
index:3,value:d
"""
eval()
取出字符串传内容,把字符串当成有效表达式:
前提是这个字符串内容是一个表达式,如下
#是一个表达式
str1 = '1+2+3' #a是一个字符串
eval(str1) #执行后结果为6
#不是一个表达式
str2 = 'abcd mmgk'
eval(str2) #执行会报错
exec()
执行字符串或compie方法编译过的字符串;
如下
str3 = 'li=[8,5,23,78,64]' #str3是一个字符串
exec(str3) #执行之后会把li当作一个list
#当打印li会出现结果
print(li)
#结果 [8, 5, 23, 78, 64]
#即把字符串中的li转换为了一个list类型的变量
filter()
过滤器,过滤器内置函数有两个参数
- 参数一为一个函数
- 参数二为一个可迭代对象
执行后如果结果为True,保留,如果为False,弃用
#过滤函数
def fun(x):
return x>30
li = [5,8,16,25,14,66,53,46,79,55,87]
#使用过滤器
list(filter(fun,li))
#处理后得到的结果为[66, 53, 46, 79, 55, 87]
#3filter执行了函数fun,其中对于列表中元素>30的数据进行了判断,为真保留,为假丢弃
map()
执行对应的函数,返回的结果保存到map对象中,可以用list转化来得到结果。
代码演示:
def fun(i):
return i*10
li = [1,2,3,4]
#调用map函数
list(map(fun,li))
#将列表中的每个元素传入函数fun中,然后执行i*10,结果返回到map对象
#结果 [10,20,30,40]
#将列表的每个元素转换为字符串
map(str,li)
zip()
可以将字典列表互相转换,对象逐一配对。
li1=[1,2,3,4]
li2=['a','b','c','d']
#调用zip函数,返回的是一个zip对象,可以用for循环依次取得结果
a = zip(li1,li2)
print(dict(a))
#结果 {1: 'a', 2: 'b', 3: 'c', 4: 'd'}
for i,value in a:
print('i={},value={}'.format(i,value))
#结果
"""
i=1,value=a
i=2,value=b
i=3,value=c
i=4,value=d
"""
匿名函数
匿名函数关键字 lambda
函数比较简单的情况下,就可以写成匿名函数的形式,增加代码可读性。
定义匿名函数的形式:
lambda 参数:表达式
一个简单的匿名函数如下:
fun = lambda a:a>10
#使用
fun(10)
#结果为False 即相当于fun(10)执行了匿名函数 10>10的比较,结果为假
配合过滤函数使用,得到想要的结果
li=[3,20,4,6,19,8,23,76,58,97]
#下面匿名函数执行比较列表中的每个元素是否>20,大于20的结果放入a列表中
a=list(filter(lambda x:x>20,li))
print(a)
#结果为 [23, 76, 58, 97]
把匿名函数当作一个函数的参数,通过执行对应的函数来得到结果
#一个函数,对这个函数的参数传入匿名函数
def my_fun(a,b,func):
c = func(a,b)
return c
#调用函数,其中func参数换成匿名函数形式,匿名函数执行两个数相加
num = my_fun(11,22,lambda x,y:x+y)
print(num)
#结果为33 匿名函数在my_fun函数中执行了11+22的操作
递归函数
函数内函数自己调用自己被称为递归函数,所以在递归的时候,需要给出一个限定,来结束对自身的调用。
因为递归有一个深度,超出深度,会报错,所以不建议使用递归。
例如求一个数的阶乘,可以使用递归来实现。
def func(num):
if num>1:
return num*func(num-1) #函数func中再次调用了自身func
else:
return num
#使用,求10的阶乘
res = func(10)
print(res)
#结果 3628800
回调函数
一个函数,传入另一个函数中,供另一个函数调用,被成为回调。
#函数a
def funa():
print('this is funa')
#函数b
def funb(fun):
fun() #参数加上括号,相当于一个函数的调用
print('this is funb')
#使用,对函数funb中的参数传参为funa的函数名
funb(funa)
#打印结果
"""
this is funa
this is funb
"""
#相当与在函数b中调用了函数a,打印'this is funa',然后在执行后续的打印代码'this is funb'
闭包
了解闭包许需要知道什么是函数体。
函数体:函数只有在调用的时候才执行,如果直接使用一个函数的函数名,则这个函数名是一个函数体,及函数在内存中的的地址。
而在函数里面再定义一个函数,并且外层函数返回了内层函数的函数体,而内层函数使用了外层函数的变量,被称为闭包。
#闭包的示例
def func1():
def func2():
print('内层函数2')
return func2 #外层函数返回了一个函数体(地址),没有加(),表示函数还未执行
#使用,用一个变量接住func1的返回值
a=func1()
#此时a相当于接受了func1()执行后的返回值func2,即a=func2
#当把a再加上一个括号,就相当于func2加上了一个括号(),相当于执行了func2()函数
a()
#得到打印的信息
#内层函数2
global关键字
函数有一个作用域,函数内作用域即从函数开始到函数结束即为函数的作用域。
在函数作用域里面如果想取到外面在函数之前定义的变量,但是这个变量是无法修改的,如果想修改这个变量,需要利用global关键字。
利用这个关键字类声明,这个变量可以在函数内被修改
a=100 #函数外定义了变量a
#如果不加global声明对a进行修改
def fun1():
a=200
print(a)
#执行打印a的结果还是100,说明在函数fun1内a的修改不成功,因为在函数fun1中a相当于一个局部变量,与外面的a没有任何关系
#函数内部如果想改变变量a,需要加上global声明
def fun2():
global a
a=400
print(a)
#结果为400 表示a在函数内可以被改变
nonlocal关键字
一般用在函数的嵌套中,可以让内层的函数使用外层函数中的局部变量。
def fun1():
a=100
def fun2(): #内层函数
nonlocal a #需要使用外层函数的变量a,需要加上nonlocal来声明
a+=1
print(a)
return fun2