什么是函数:可以实现特定功能的一段代码块
优点:简化代码结构,增加代码复用度,提高代码可读性,方便维护
1.简单函数
def simpleFun():
print('我是simpleFun函数')
# 调用simpleFun()
simpleFun() # 执行结果 输出:我是simpleFun函数
2.带参数的函数
def parameterFun(x, y):
print('{}+{}的结果是:{}'.format(x, y, x+y))
parameterFun(10, 15) # 执行结果 输出:10+15的结果是:25
# 形参:带默认值参数,有默认的形参要靠后
def defaultsParameterFun(x, y=15):
print('{}+{}的结果是:{}'.format(x, y, x + y))
defaultsParameterFun(10) # 执行结果 输出:10+15的结果是:25 y的默认值是15
defaultsParameterFun(10, 20) # 执行结果 输出:10+20的结果是:30
# 1.如果形参没有默认值,调用的时候必须传递实参,并且实参的数量和位置要和形参一致
# 2.如果有的形参有默认值,定义函数的时候有默认值的形参要放在后面
# 3.如果形参有默认值那么不传递对应的实参没有关系,如果传递实参,实参值会把默认值给覆盖
# 实参:关键字参数 调用时实参写成:形参名 = 实参值
def keywordsParameterFun(x, y):
print('{}+{}的结果是:{}'.format(x, y, x + y))
keywordsParameterFun(x=10,y=5) # 执行结果 输出:10+5的结果是:15
# 1.如果给其中一个参数设置了关键字,其他需要传递的参数也必须设置关键字
# 2.设置了关键字参数,实参的顺序可以和实参不一样
# 形参:不定长参数
def lndefinitelengthParameterFun(*args):
print(args)
lndefinitelengthParameterFun(1, 2, 3, 4, 5)
# 执行结果 输出(1, 2, 3, 4, 5) 函数是以元组的形式接收参数
def lndefinitelengthParameterFun(a, b, *args):
print(a,b,args)
lndefinitelengthParameterFun(1,2,3,4)
# 执行结果 输出 1 2 (3, 4)
# 总结,普通形参和不定长形参一起使用的时候,普通形参在前,普通形参的默认值会被覆盖,并且普通形参不能使用关键字参数
# 普通形参在后面时,没有默认值的普通形参必须要用关键字实参传递值
# 不定长关键字参数
def lndefinitelengthKeywordsParameterFun(**kwargs):
print(kwargs)
lndefinitelengthKeywordsParameterFun(x=10, y=20, z=30)
# 执行结果 输出:{'x': 10, 'y': 20, 'z': 30}
# 函数时以字典的形式接收参数
# 普通形参和不定长关键字参数一起使用的时候,普通形参的名字不能和定长关键字参数有重复,并且普通参数要在前面
# 不定长参数和不定长关键字参数一起使用时,不定长关键字参数要在后面
def func(*args,**kwargs):
print(args,kwargs)
func(1,2,3,name='cpx',password='cpx123')
# 执行结果 输出(1, 2, 3) {'name': 'cpx', 'password': 'cpx123'}
# 普通形参和他们一起用的情况参考上面
# *作为实参
def func(a,b,c,d):
print(a,b,c,d)
list1 = [1, 2, 3, 4]
func(*list1) # 执行结果 输出:1 2 3 4
# **作为实参
def func(**dict):
dict['cpx'] = 'x'
print(dict)
dict1 = {'1':1,'2':2}
func(**dict1) #执行结果 输出:{'1': 1, '2': 2}
print(dict1) # 输出结果:{'1': 1, '2': 2}
# 和直接传递字典的却别是在函数内修改参数的值,参数本身不会被修改,这是把可变参数类型改成不可变参数类型了?
# 参数时可变数据类型和不可变数据类型的区别
# 参数是不可变数据类型
def func(a):
a = a+10
print(a) # 输出结果 20
a = 10
func(a)
print(a) # 输出结果 10
# 不可变数据类型作为参数时,函数内对参数的修改不会影响参数本身
# 参数为可变数据类型时
def func(dict1):
dict1['cpx'] = 'csl'
print(dict1) # 输出结果 : {'x': 'x1', 'y': 'y1', 'cpx': 'csl'}
d = {'x':'x1','y':'y1'}
func(d)
print(d) # 输出结果:{'x': 'x1', 'y': 'y1', 'cpx': 'csl'}
# 函数内修改参数,参数本身也会跟着改变
3.有返回值的函数
def returnFun(x, y = 2):
return x**y # 返回x的y次幂的值 执行return之后整个函数结束
print(returnFun(10)) # 执行结果 输出:100
# 模拟实现popitem()函数功能, 并返回被删除键值对
# 随机删除一个字典元素
d = {"头条": "抖音", "阿里巴巴": "闲鱼", "腾讯": "微信"}
d.popitem()
print(d) # 执行结果 输出:{'头条': '抖音', '阿里巴巴': '闲鱼'} 执行结果不唯一
import random
def pop_item(dict):
keys = dict.keys()
klist = list(keys)
# 随机选择key一个效果
key = random.choice(klist)
# 获取key 和 value
key, value = key, dict[key]
del dict[key]
return key, value
d = {"头条": "抖音", "阿里巴巴": "闲鱼", "腾讯": "微信"}
key, value = pop_item(d)
print('被删除的key是:{},被删除的value是:{},剩下d的值是:{}'.format(key, value,d))
# 执行结果 输出:被删除的key是:头条,被删除的value是:抖音,剩下d的值是:{'阿里巴巴': '闲鱼', '腾讯': '微信'} 结果不唯一
4.匿名函数
# 普通匿名函数
add = lambda a,b:a+b
print(add(3,10)) # 输出结果 13
# 直接调用的匿名函数
print((lambda a,b:a+b)(10,10)) # 输出结果 20
# 带默认值的匿名函数
add = lambda a= 1 ,b= 2:a+b
print(add(10)) # 输出结果:12
# 没有参数的匿名函数
a = 10
b = 15
n = lambda: a+b
print(n()) # 输出结果25
5.递归函数
# 自己调用自己,满足条件就return,使用递归函数要注意深度,否则浪费计算机资源
def recursiveFun(n):
if n == 1:
return 1
return n*recursiveFun(n-1)
print(recursiveFun(3)) # 输出6
6.生成器
# 写法一
def lg(num):
for i in range(1, num):
yield i
l = lg(10)
print(sum(l)) # 输出结果:45
print(sum(l)) # 输出结果:0 生成只使用一次,如果要再次使用需要再次调用
# 写法二
gs = (i for i in range(1, 10))
print(sum(gs)) # 输出结果:45
# 生成器,保存的是算法,节省内存
7.装饰器
def demo(y):
print("demo func")
y()
@demo
def func():
print("func")
# 带参数的装饰器
def demo(func):
def inner(age):
if age<=10:
mystr = "children"
elif age <= 20:
mystr = "midman"
else:
mystr = "oldman"
return func(mystr)
return inner
@demo
def func(p):
print("你是一个这样的",p)
func(60)
# 作用: 程序代码运行时,动态增加功能
# 本质: 就是一个闭包,返回了函数的高阶函数
# 好处: 遵序开闭原则,对修改关闭,对扩展开放