什么是函数
函数本质上就是一个封装后可以重复利用的代码片段,需要使用的时候直接调用就可以了,比如前面所使用的type函数,print函数。这些都是Python的内置函数,Python官方的开发者底层封装好后我们可以拿过来直接使用,不用关心底层是如何实现的。
为什么要定义函数
提升代码的可复用性和结构化,函数的封装是一种思想,可以不用函数也能完成但是效率低,代码重复量大!
如何定义函数
在Python中,函数的定义需要使用到 def ,后面跟上函数的名称、括号,括号里面的参数,冒号,然后在缩进的语句块中用 return 返回函数执行的结果,也可以不用return,默认返回None。
def 函数名称(参数):
代码块
return 结果
# 定义一个函数输入蓝桥老师是全宇宙最帅的男人
def print_text():
print("蓝桥老师是全宇宙最帅的男人!")
函数的调用
函数在被调用之前必须声明,否则无法调用。print,type等函数已经在Python底层中定义好了,所以我们可以直接调用,无需关心内部如何实现。
# 定义一个函数输入蓝桥老师是全宇宙最帅的男人
def print_text():
print("蓝桥老师是全宇宙最帅的男人!")
# 调用这个函数
print_text()
'''
输出结果:
蓝桥老师是全宇宙最帅的男人!
'''
在Python程序中,如果遇到函数的定义,编译器会自动跳过,执行函数之后的代码,如果想调用函数直接调用即可,当程序执行到第二行发现这是一个函数声明,直接调到函数末尾,到第6行调用这个函数,再进入这个函数体之内执行代码。直到结束,这就是代码的运行的过程。
带参函数
函数可以通过外部传递参数,参数分为形参和实参:
# 没有参数, 固定值没有办法动态改变
def sum_num():
a = 10
b = 20
sum = a + b
print("%d+%d=%d" % (a, b, sum))
sum_num()
# 带参数版本
def sum_num(a, b):
sum = a + b
print("%d+%d=%d" % (a, b, sum))
num1 = int(input("请输入第一个数字"))
num2 = int(input("请输入第二个数字"))
sum_num(num1, num2)
常规而言,函数默认有几个形式参数,在外部调用时就需要传递多少个实参。
缺省参数
除了上面的常规传递参数的方式之外,还有 缺省参数 主要特点如下:
- 如果外部调用该函数没有给缺省参数传递参数,该形参直接取默认参数值;
- 如果外部调用时给缺省参数传递了参数,那么该形参的值应该等于外部传递的参数;
- 缺省参数只能放置在常规形式参数的后面
应用场景: 当我们希望默认执行某些东西的时候可以使用,如print函数默认会在输出的内容后面加个换行\
def sum(a,b=22):
result = a + b
print(result)
sum(11)
'''
输入出结果:
33
'''
参数传递方式默认从左往右传递,也可指定参数传递(命名参数),注意命名参数一定要和函数定义时参数一致
def sum(a,b=22,c=10):
result = a + c
sum(11,c=11)
'''
输入出结果:
22
'''
可变长参数
当我们不确定要传入参数的具体个数的时候可以选择在定义函数的时候,添加不定长参数。
print函数相对来说比较熟悉,我们可以观察下面的代码。
a = 10
b = True
c = 1.1
d = "你好"
print(a)
print(a,b)
print(a,b,c)
print(a,b,c,d)
'''
输出结果:
10
10 True
10 True 1.1
10 True 1.1 你好
'''
问题来了,这print函数到底能传递几个参数?其实没有限制,想传多少参数都可以,这就是不定长参数。不定长参数主要分为两种,分别是*args和**kwargs**。**
def test(a,b,*args)
'''
1、除去必选参数外,多余参数都会传入可变长参数 args ,接收值以元组进行封装
2、可变长参数只能放置在参数列表的最后面
3、该参数可不传递
'''
def test(a,b,**kwargs)
'''
kwargs 接收的参数形式为 参数名 = 参数值,以字典形式存储数据传入到函数中
该参数可不传递
'''
# 不定长参数 *args
def test1(a,b,*args):
print(a,b,args)
# 传递多个参数
test1(1,2,3,4,5,False)
'''
输出结果:
1 2 (3, 4, 5, False)
总结:不定长参数*args以元组的方式进行封装
'''
# 不传不定长参数
test1(1,2)
'''
输出结果:
1 2 ()
总结:如果没有为函数传递不定长参数,默认为空元组
'''
# 思考:如何在函数内从不定长参数取出每一个值呢?
# 不定长参数 **kwargs
def test2(a,b,**kwargs):
print(a,b,kwargs)
# 传递多个参数
test2(1,2,name='lanqiao',age = 18)
'''
输出结果:
1 2 {'name': 'lanqiao', 'age': 18}
总结:不定长参数**kwargs将传入的参数以字典格式封装
'''
# 不传不定长参数
test2(1,2)
'''
输出结果:
1 2 {}
总结:如果没有为函数传递不定长参数,默认为空字典
'''
# *args 与 **kwargs组合
test3(a,b,**kwargs,*args) # 程序报错
'''
总结:不定长参数*args在**kwargs前面顺序不能颠倒
'''
# 定义一个函数,计算传入的数字的和
def sum_num(a,b,*args):
result = a + b
for num in args:
result += num
print(result)
sum = sum_num(12,23,12,34,56)
'''
输出结果:
137
'''
自动拆包
def test(a,b,*args,**kwargs):
print(a)
print(b)
print(args)
print(kwargs)
A = (1,2,3)
B = {"name":"laowang"}
# a,b分别都被当成一个元素传入*args
test(11,22,A,B)
'''
输出结果:
11
22
((1, 2, 3), {'name': 'laowang'})
{}
'''
# 这里会自动拆包,将元组和字典拆分成单个元素和键值对
test(11,22,*A,**B)
'''
输出结果:
11
22
(1, 2, 3)
{'name': 'laowang'}
'''
函数的返回值
函数的返回值根据具体情况而定,如果函数没有return返回值,默认会返回None(空值),空值不是False,不是0,空就是空。
为什么需要返回值?没有返回值,函数最终执行的结果外界将无法使用,仅能在函数内部使用,字典.getkeys 返回值就是所有的key,同时返回值还可以向外界传递一个信息,比如代码执行是否成功(状态码)方便下一步进行。
1、无参 无返回值
2、无参 有返回值
3、有参 无返回值
4、有参 有返回值
# 获取温度(摄氏度)
def get_noun():
noun = 25
return noun
# 将摄氏度转化成华氏度
huashi_noun = get_noun() * 33.8
print("当前温度华氏度为:%g" % huashi_noun)
复制请点击Error复制成功
函数返回多个值
return 一次性只能返回一个值,如果想要返回多个值,可以利用字典,列表,元组等将多个值封装,一次性返回
应用场景:通过一个方法获取完整的天气信息 城市,温度,穿衣指数,pm2.5\
def get_num():
a = 10
b = 20
c = 30
# return [a, b, c]
# 默认封装成元组
return a,b,c
函数嵌套使用
在一个函数中调用了另外一个函数,这就是函数的嵌套使用
def test_01():
print("--111--")
print("这里是1号代码")
print("--112--")
def test_02():
print("--221--")
test_01()
print("--222--")
def test_03():
print("--331--")
test_02()
print("--332--")
test_03()
'''
输出结果:
--331--
--221--
--111--
这里是1号代码
--112--
--222--
--332--
'''
# 用户输入
num1 = int(input("请输入第一个值:"))
num2 = int(input("请输入第二个值:"))
num3 = int(input("请输入第三个值:"))
# 求和
def sum_number(n1, n2, n3):
result = n1 + n2 + n3
# return "%d+%d+%d=%d" % (n1, n2, n3, result)
return result
# 计算平均值
def averang_number(n1, n2, n3):
result = sum_number(n1, n2, n3)/3
return result
# sum_n = sum_number(num1, num2, num3)
# print(sum)
aver_n = averang_number(num1, num2, num3)
print(aver_n)
局部变量与全局变量
在Python中,变量根据位置的不同,其所影响的范围也不同。比如自家的卫生间只能自家人用,公共卫生间所有人都可以用(杠精说:家里来客人了客人也可以用自家的卫生间啊)
局部变量 : 在函数里面定义的变量都是局部变量,只能在函数内部使用. **全局变量 : 在函数之外定义的变量,在任何函数之内都可以使用 **注意:如果局部变量和全局变量重名,就近原则局部变量优先
text = "小东西"
def test1():
# 定义局部变量a
a = 10
# 使用全局变量
print(text)
def test2():
# 使用全局变量
print(text)
def test3():
# 定义局部变量
text = 16
# 如果局部变量和全局变量重名,就近原则,局部变量优先
print(text)
# 此处无法使用a
# print(a)
test3()
局部变量和全局变量即使名字相同但是本质上是两个变量,使用***global***关键字指定当前变量为全局变量\
text = "我的小宝贝"
def up_data():
global text
text = "爱老虎油!"
up_data()
print(text)
'''
输出结果:
爱老虎油!
a = [100]
def test(num):
num = num + num
print(num)
test(a)
print(a)
'''
输出结果
函数内的num值 [100, 100]
全局变量a的值 [100]
'''
a = [100]
def test(num):
num += num
print("函数内的num值",num)
# 将a的值当做参数传递
test(a)
print("全局变量a的值",a)
'''
输出结果
函数内的num值 [100, 100]
全局变量a的值 [100, 100]
'''
分析总结:
num += num :+= num指向谁就对谁进行修改,当a传递进来的时候,a是可变类型[100],此时直接修改 **num = num + num: 先执行等于号右边,得到的结果在内存中暂时保存,此时左边的局部变量num指向这个新的内存地址**
递归
递归就是函数自己调用自己。请注意使用递归需要设置结束条件,若无结束条件,程序会造成内存溢出。
'''
什么是阶乘?
5的阶乘就是 5*4*3*2*1
3的阶乘就是 3*2*1
需求:定义一个函数,计算传入的数值的阶乘
'''
# 常规写法
def get_while_num(num):
i = 1
result = 1
while i < num:
result *= i
i+=1
return result
# 递归写法
def get_number(num):
if num > 1:
return num*get_number(num-1)
else:
return num
number = get_while_num(5)
print("常规写法:",number)
number1 = get_number(5)
print("递归写法",number1)
'''
输出结果:
120
120
'''
匿名函数 lambda
我们前面讲过Python中,如果想要使用函数必须要先声明再调用,每一个函数都有自己的名字。但是有这么个奇葩函数它是没有名字的也不要声明直接就能用,但是想要用好,还是需要一定时间的积累,它就是lambda匿名函数。
1.匿名函数有关键字 lamb
da 修饰;
2.匿名函数冒号 : 之前的是函数的参数,匿名函数可以是无参匿名函数,也可以是带参匿名函数;
3.匿名函数冒号 : 之后是表达式,匿名函数不需要写 return,表达式的结果就是返回值;
a = lambda x,y:x+y
b = a(12,14)
print(b)
'''
输出结果
26
'''
# 上面的功能传统函数写法如下
def sum(num1,num2):
result = num1 + num2
return result
a = sum(12,14)
print(a)
匿名函数和普通函数对比之下,匿名函数的使用能让代码更加简洁,当然匿名函数使用场景适用于比较简单的需求,对于复杂的计算,匿名函数是无法完成的;
'''
需求 : 定义函数,将传入的字符串按照空格拆分,将拆分完的字符串拼接成一个完整的字符串
'''
str1 = "laowang is sing_dog "
#普通函数
def get_str(str1):
# 1.将字符串拆分为列表
list1 = str1.split(" ")
# 2.将列表转为字符串并返回字符串
return "".join(list1)
# 将1/2两步合并为一步完成
# return "".join(str1.split(" "))
print("打印原始字符串:",str1)
print("调用普通函数获取字符串拆分结果:",get_str(str1))
#匿名函数
f0 = lambda a:"".join(a.split(" "))
print("调用匿名函数获取字符串拆分结果:",f0(str1))
'''
输出结果:
打印原始字符串: laowang is sing_dog
调用普通函数获取字符串拆分结果: laowangissing_dog
调用匿名函数获取字符串拆分结果: laowangissing_dog
'''
思考:lambda函数中能使用缺省函数、不定长参数吗?动手测试下
# 将匿名函数当做参数传递
def test(a,b,funct):
result = funct(a,b)
return result
num = test(3,4,lambda x,y:x*y)
print(num)
'''
需求:比较两个数值的大小,返回较大的值
'''
def compare(a,b):
return a if a > b else b # 返回较大的值
# 定义匿名函数
function0 = lambda b:b*10
# 匿名函数作为参数传递
compare(100,function0(3))
# 上面两行可以简写成一行
compare(100,(lambda b:b*10)(3))
# 使用匿名函数对列表
test_list0 = [1,43,566,786,34,64,4,345]
# 列表排序
test_list0.sort()
print(test_list0)
# 通过key排序
test_list = [{"name":"老王","age":"10"},{"name":"老李","age":"25"},{"name":"二狗","age":"33"}]
test_list.sort(key = lambda x:x["age"])
print(test_list)
lamb = input("请输入lambda表达式:")
lamb = eval(lamb)
test02(10,20,lamb)