函数
是可以重复使用进行用来实现单一,或相关联功能的代码块。
一、无入参的函数
#函数 def func1(): '''函数的功能描述''' print("in the func1") return 0 #过程 def func2(): '''打印in the func2''' print("in the func2") x = func1() y = func2() print(x) print(y)
上述代码中,func1中有return 0;func2没有返回;在后续的赋值操作时,可以看到x=0;y为None
使用函数实现记录日志的功能
import time def log(): '''通过获取当前时间打日志追加到同级目录的log.txt文件中''' time_format = '%Y-%m-%d %X' time_curent = time.strftime(time_format) with open('log.txt','a+',encoding='utf-8') as f: f.write('%s this is log.... ' %time_curent) print('in the test1') log()
其中用到了time模块中的strftime方法,可以参照https://www.runoob.com/python/att-time-strftime.html中的进行参考;
函数的优点:可重复使用的,扩展性更高,使代码变得简单
函数的返回值
在第一段函数中可以发现有return
return返回值可以是多中多样的,可以不写,这样返回就是None
返回一个数字
返回一个列表
返回一个字典,都可以进行返回
如果返回多个数据
def test4(): print('in the test4') return 0,1,[0,'fdj'],{'key':'vlalue'}
那么返回的结果是以元组的形式进行返回:(0,1,[0,'fdj'],{'key':'vlalue'})
那为什么我们要有返回值
第一点:首先return是对函数的一个终结,表明到这里函数执行结束了;
def test3(): print('in the test4') return 0,1,[0,'fdj'],{'key':'vlalue'} print('in the test3')
比如上方的这段代码,return之后,后面 print('in the test3')就不会再执行了
第二点:函数的返回值,可以对后续的操作进行影响,比如我们一个返回的是1我们后续可能走这段逻辑;如果返回时0可能走另外一段逻辑
二、包含参数的函数
在对函数进行定义的时候,可以根据函数的情况,进行传参
1位置参数:
def test1(x,y,z): print(x) print(y) print(z) return 0 test1(3,2,1)
上段代码中我们给test1()传了3个参数,这种参数属于位置参数,和函数定义的参数位置一一对应
2关键字参数
def test1(x,y,z): print(x) print(y) print(z) return 0 test1(3,2,z=1)
上面的代码呢,我们按照位置传了两个参数,还指定了z=1;其中z=1这种就叫关键字参数
同样也可以全部都进行指定
比如
test1(y=3,x=2,z=1)
如果是这样:
test1(3,x=2,1)运行的时候回提示报错,原因是python中指定参数要放在位置参数的后面;
3默认参数
默认参数就是在定义函数传参的时候可以进行参数传默认值,例如
def test1(x,y,z=4): print(x) print(y) print(z) return 0 test1(3,2)
test1函数有3个参数,但是我们调用的时候只传了两个,因为有默认参数,我们可以不传;当然也可以传,这样对应得参数以最后一次传参的值为准
比如我们在使用数据库的端口号的时候就可以使用默认传参,如sql:1433 oracle:3366
4参数组
上面说的参数都是固定的,我们在现实的应用中都会出现,我们没有想好的情况,是否确定参数的个数,我们想要参数不是固定的,这个时候,就引入了参数组的概念
def test2(*args): print("so many parameter") return 0 test2(1,2,3,5)
上面的代码中*args就是定义了一个参数组,我们去调用的时候就可以函数的应用随机的去传相应的函数,便于函数后期的扩展
上面再调用test2的时候还可以这样传参test2(*[1,2,3,5])和test2(1,2,3,5)是一样的额效果,这种是将参数转为元组;
如果我想要字典的形式,可以使用如下方式
def test3(**kwargs): print(kwargs) return 1 test3(name = 'axiang',age = '28')
输出的结果是一个字典:
{name:'axiang',age:'28'}
同样还可以使用test(**{name:'axiang',age:'28'})这种方式调用
如果我想获取name对于的value的时候可以
kwargs['name']
上述的内容*args是把N个位置参数转化为元组的方式;**kwargs是把N个关键字参数转换成字典的方式
局部变量和全局变量
def change_name(name): print("before change ",name) name = 'axiang' print('after change ',name) name = 'lxiang' change_name(name) print(name)
运行结果
before change lxiang
after change axiang
lxiang
可以看到change_name函数中定义的name称之为局部变量,在顶层的定义的为全局变量,差别就是作用域不同
局部变量的作用域在函数体内;全局变量的作用域是全局的
如果想在函数中定义全局变量,可以使用global进行定义,表示为全局变量
递归函数
在函数内部自己调用自己
1.必须要有个结束条件
2.每次进入更深一层递归时,问题规模相比于上次递归都应该减少
3.递归效率不高,递归的层次过多会导致栈溢出
def calc(n): print(n) if int(n) > 0: return calc(int(n/2)) calc(10)
高阶函数
定义的函数里面调用函数,称为高阶函数
def add(a,b,f): return f(a)+f(b) res = add(3,-6,abs)#abs(-6) = 6;绝对值函数 print(res)
运行的结果是 9