函数
函数的概念:就是为了方便对代码的管理下次直接调用函数即可
- 作用:1. 方便代码的重用;2. 分解任务,简化程序逻辑 3. 使得代码更加模块化
- 函数分类:内建函数,三方函数,和自定义函数
函数的基本使用
- 简单定义:
def 函数名():
函数体 - 函数调用:直接用函数名即可:函数名()
def a():
print(2**2)
print(2**3)
print(2**4)
a()
函数的参数
- 单个参数
下面这个例子可以看到定义函数的哪里f后面是形参,下面调用的时候传入的参数才是实参
def f(num):
print(num**2)
print(num**3)
print(num**4)
f(2)
- 多个参数
def sum(num1,num2):
print(num1+num2)
sum(1,2)
sum(num1=6,num2=4)
- 不定长参数:适用范围是如果函数体需要处理的数据不确定的长度
方式一:形参前面加上星号,以元组的形式接受传递过来的参数。 (固定写法是args)
在函数名的括号里面加上args,代表接受到的是个元组,因为元组是不可变的
def Sum(*t):
print(t,type(t))
result = 0
for v in t:
print(v)
result +=v
print(result)
Sum(3,4,5,6)
方式二:形参前面加上两个星号,代表着以字典的形式接受参数,使用的时候必须要以关键字参数的形式来进行使用(**kwargs)
def mySun(**kwargs):
print(kwargs,type(kwargs))
mySun(name = 'sz',age = 18)
- 参数的拆包和装包
装包:把传递的参数包装成一个集合,称之为‘装包’
拆包:把集合参数,再次分解成单独的个体,称之为“拆包”
def sum(a,b,c,d):
print(a+b+c+d)
def test(*args):
print(args)
#拆包
print(*args)
sum(*args)
test(1,2,3,4)
def sum(a, b):
print(a)
print(b)
def test(**kwargs):
print(kwargs) # 打印接收到的是什么东西
# 拆包操作 用 ** 来进行拆包操作
sum(**kwargs) #如果不加*的话,就相当于传入了一个参数
#如果加两个星星的话,代表把拆好的包放进去
# **的要以关键字参数的形式调用
test(a=1, b=2)
函数的缺省参数
就是在使用的时候不填写的时候会自动选择默认的值,使用方法就是在定义函数的时候,形参后面等于一个默认值就可以。
def hit(someone='汤圆'):
print('打',someone)
hit('张三')
hit()
函数的参数注意事项
我们看一下下面的代码,首先b = 10,现在内存中开辟了一块空间10,然后b指向10,这时候要调用这个函数change的时候,把b传进去,函数内部接收到的是num这个参数,在函数内部呢又进行了一个赋值操作,将666赋值给num,但是10是不可变的,这时候只能在内存中开辟一块新的地址666,num指向666
注意:Python中不可变的数据类型:整形,字符串和元组
函数的返回值:当我们通过某个函数,处理好数据之后,想要拿到处理后的结果
def cal(a,b):
sum = a+b
cha = a-b
return (sum,cha)
result = cal(11,5)
print(result)
sum,cha = cal(11,5)
print(sum,cha)
函数的使用描述
偏函数
def sum(a,b,c,d=1):
print(a+b+c+d)
import functools
newFunc = functools.partial(sum,c=5)
print(newFunc)
newFunc(1,2)
使用场景:
高阶函数:
函数可以作为一个变量传给下一个函数
案例:动态的计算两个变量
def cal(num1,num2,calFunc):
result = calFunc(num1,num2)
print(result)
def sum(a,b):
return a+b
def jian(a,b):
return a-b
cal(6,2,sum)
cal(6,2,jian)
返回函数
def getFunc(flag):
# 1. 先定义几个函数
def sum(a,b,c):
return a+b+c
def jian(a,b,c):
return a-b-c
# 2. 根据不同的flag值来返回不同的操作函数
if flag == '+':
return sum
elif flag =='-':
return jian
result = getFunc('+')
print(result,type(result))
res = result(1,2,5)
print(res)
匿名函数(lambda函数)
表达式的结果就是返回值
#首先lambda就是一个函数,在后面在加个括号就相当于是调用函数
result = (lambda x,y:x+y)(1,2)
print(result)
re = lambda x,y:x+y
print(re(4,5))
下面是匿名函数的应用,以我们之前写的sort函数为例子
l = [{'name':'sz','age':18},{'name':'sz1','age':22},{'name':'sz2','age':17}]
def getKey(x):
return x['age']
result = sorted(l,key=getKey)
print(result)
这个例子我们可以看到,这里定义的函数只能在这里为了key使用,这时候比较麻烦,不如用匿名函数来定义简单容易。
l = [{'name':'sz','age':18},{'name':'sz1','age':22},{'name':'sz2','age':17}]
result = sorted(l,key=lambda x:x['age'])
print(result)
Python函数的闭包
def test():
a = 10
def test1():
print(a)
return test1()
newFunc = test()
newFunc
闭包的案例:
普通的写法:
#案例:打印分割线print(----------------abc---------------)
def line_config(content,length):
print('-'*(length//2) + content + '-'*(length))
line_config('闭包',20)
下面是用闭包的形式来写:
#案例:打印分割线print(----------------abc---------------)
def line_config(content,length):
def line():
print('-'*(length//2) + content + '-'*(length))
return line()
line1 = line_config('闭包',20)
line1
闭包注意事项
此时这个result起始就是test2函数
下面这个例子第一个print打印的是test函数里面的num=10,接着调用test2打印num=666,因为test2里面有定义num,第三个print打印的也是num=10,说明函数test2里面的num=666没有赋值,而是新创建的一个变量
当声明之后才可以
注意事项2:
def test():
a = 1
def test2():
print(a)
a = 2
return test2()
newFunc = test()
newFunc
为什么这里打印是2呢?因为函数如果不调用的话是不会使用的,这里如果调用test函数,先执行a=1,不会执行test2,而是执行a=2,等后面在调用的时候才执行test2函数,但是这时候a已经变成2了。
Python函数的装饰器:在函数名以及函数体不改变的情况下,给一个函数附加一些额外的代码
案例:
def fss():
print('发说说')
def ftp():
print('发图片')
#相关逻辑代码
index = 1
if index ==1:
fss()
else:
ftp()
比如说我们想要在每次执行的时候先加上一个登录界面,,如果直接在业务逻辑里面添加呢,业务逻辑非常多,这时候会带来严重的冗余,代码复用性比较差。
所以可以选择在功能函数里面修改,这时候只需要改一次即可,方便代码重用。
下面是利用装饰器的形式来写的,不改变定义函数和逻辑代码,另外定义一个函数
def checkLogin(func):
def inner():
print('登录验证。。。。。。。。。')
func()
return inner
@checkLogin
def fss():
print('发说说')
#相当于 fss = checkLogin(fss)
@checkLogin
def ftp():
print('发图片')
#相关逻辑代码
index = 1
if index ==1:
fss()
else:
ftp()
这里我们看到用*来进行接受并且解包
生成器:是一个特殊的迭代器(迭代器的层次更高)
- 创建方式1:生成器表达式:把列表推导式【】修改成()
下面是列表推导式
l = [i for i in range(1,10) if i %2 ==0]
print(l)
l1 = (i for i in range(1,10) if i %2 ==0)
print(l1)
print(next(l1)) #上一次运行到哪里,下一次next就继续执行
print(next(l1))
print(l1.__next__())
- 创建方式2:生成器函数,函数中包含yield语句,这个函数执行结果就是生成器
我们可以看到当执行next函数的时候先执行yield1之前的,然后到yield1,返回当前状态然后再执行,想如果再执行next的时候,结果应该是a,2
def test():
print('开始')
yield 1
print('a')
yield 2
print('b')
g = test()
print(g)
print(next(g))
- 产生数据的方法:生成器具备可迭代特性,所以使用next()函数等价于生成器.next()再或者用for in也可以进行
- 生成器的几个方法:send方法
下面的例子我们可以看到第一个next执行只是会输出一个状态1然后挂起来,第二次next执行输出result,然后到第二个状态哪里去
def test():
result = yield 1
print(result)
result1 = yield 2
print(result1)
g = test()
print(g.__next__())
print(g.__next__())
def test():
result = yield 1
print(result)
result1 = yield 2
print(result1)
g = test()
# print(g.__next__())
# print(g.__next__())
print(g.send(None)) #第一次只能传个None
print(g.send(6))
- 生成器的几个方法:close方法
如图所示我们如果用三个next函数的时候输出是1,a,2,b,3就结束了,当再进行next的时候就报错
注意事项:
递归函数:函数A内部继续再次调用A
下面这个例子就是递归的形式,每次递归的时候会5!转换成5 *4的阶乘,然后依次转换
def jiecheng(n):
if n ==1:
return 1
return n * jiecheng(n-1)
result = jiecheng(5)
print(result)
函数的作用域
a = 100
def test():
a=10
print(a)
print(a)
test()
print(a)
我们可以看到,函数里面的a根本不会改变外面的a,所以说里面相当于定义了一个新的变量啊
而我们加上global后,函数里面的a变成全局变量,这时候函数里面相当于更改a的值了
a = 100
def test():
global a
a=10
print(a)
print(a)
test()
print(a)