文章目录
前言
本篇文章的目的是带领大家从零开始认识函数
,作为函数学习的第一课,本章内容是非常重要的!!!在学习函数之前,我们要明白以下几点:
-
什么是函数?
在Python中,函数是一段组织好的、可重复使用的、用来实现单一或相关联功能的代码块
。你已经定义了一个函数,就可以在你的程序中多次
调用这个函数。它相当于一个功能,我们可以通过定义的函数名,重复使用这个功能,而这个功能的作用则由你自己来定义 -
为什么要使用函数?
当我们在开发程序时,可能会重复
用到一些相同的代码,这些代码通常用来实现特定的功能
,若我们需要在程序的多个地方使用这些代码,一般会将他们复制然后粘贴,但这样编写的代码会显得冗余
,还会浪费不必要的时间,所以python中内置了函数这个功能,通过将特定的几段代码定义为一个函数
,后续使用这些代码只需要调用函数名
即可 -
函数的作用是什么?
1、将一段代码定义为一个函数,这样只需调用函数即可使用代码,减少代码冗余,避免重复代码
2、定义好函数后,在程序出现问题时,只需检查函数中的代码即可,便于维护
3、函数定义后可随时修改其中的代码,这样我们就能自定义的增加或减少函数的功能,易于扩展
1、函数
1.1 函数的本质
函数在本质上其实和变量是一样的,如下:
- 变量保存数据,
函数保存的是功能
- 函数和变量的基本原则都是:
先定义,在使用
- 函数名和变量名都指向的是一个
内存空间
,用于保存定义的功能或数据
- 函数名和变量名的
命名规则相同
对变量的本质不是很熟悉的朋友,可以读这篇文章:http://t.csdnimg.cn/ugmAi
1.2 定义函数
语法格式:
def 函数名():
代码1
代码2
... ...
如:
def ah():
print(666) # 缩进用来区分不同层级的代码
# 程序运行后不会有任何结果
注意:
定义好函数后,运行程序并不会不会执行其中代码,需要通过调用函数名才会执行这些代码
1.3 调用函数
语法格式:
函数名()
def ah():
print(666)
ah() # 调用定义的函数
输出结果:
666
1.4 深入解析函数
- 定义函数时,发生了什么事情?
- 在内存中开辟了一个空间
- 将定义的代码块放入到这个空间中
- 将内存地址绑定给这个函数名
- 调用函数的本质
格式:函数名()
,其实就是内存地址()
;因为函数名绑定给了内存地址,加上括号
才是表示调用这个函数,也就是执行这个内存地址中保存的代码
案例1:
def ah():
print(666)
print(ah) # 直接打印函数名,输出该函数名绑定的内存地址相关信息
输出结果:
<function ah at 0x000001B3621D81F0>
案例2:
def ah():
print(666)
b = ah # 将函数名绑定给变量b后,他们内存地址就相同了,通过变量b也可以直接调用函数
b() # 输出结果:666
- 函数的叠加调用
定义一个函数时,可以在里面放任何代码,同样也可以调用其他函数;如:
def a():
print(666)
def b():
a() # 在函数b中调用函数a,当调用函数b时,两个函数中的代码都会执行
b() # 输出结果:666
- 函数的基本原则
- 先定义,再使用;指的是代码执行的顺序,并不是书写顺序
- 定义函数后,并不会执行其中的代码,在被函数名调用后,才会执行其中的代码;所以我们在定义函数时,可以先使用还未定义的变量,这样在调用时也不会报错
案例:
def a():
b() # 先使用还未定义的函数b,不会报错
def b():
print(666)
a() # 调用函数a,输出结果:666
说明:
从上面可以看到,我们在定义函数a时在其中使用了函数b
,但函数b此时还未定义,结果却没有报错;这里我们就要理解,函数先定义,在使用的真正含义
,因为函数在定义时并不会执行其中的代码,所以实际上只是将这个函数的代码放入了内存空间
;而只有在我们调用它时,函数中的代码才会执行;所以实际上当我们在调用函数a时,函数 a和b已经被定义了
;而我们执行的则是内存空间中的代码
- 内置函数
函数就是使用关键字
def
,通过特定语法将一堆代码块组合成可以让我们任意使用的功能;而像这种功能我们在python中是经常使用的,如:print(),input(),strip()
等等,他们都属于内置函数
- 为什么我们在使用内置函数时,不用定义呢?
因为python已经提前帮我们定义好了,这些函数都放在python的内置模块中;我们可以直接使用 - 若我们
定义的函数名与内置函数名相同
,内置函数会被覆盖掉;如:
def input():
print(666)
input() # 输出结果:666
说明:
可以看到,原本input()函数是用于接收数据的,但将它重新定义调用后,变成了我们自定义的功能,原来的功能已经被覆盖
掉了,所以在平常定义函数时,要注意不能与python中的内置函数重名
,以免影响使用
1.5 定义函数的完整语法
语法格式:
def 函数名(参数1,参数2,...)
代码1
代码2
return 返回值
从上面可以看到,完整的语法格式中,多出了两个元素,参数和return
,这两个元素不写,函数依然能够定义,它们的作用主要是为了丰富函数的功能,使函数使用起来更加方便,接下来我会逐步分析这两个元素的作用
1.5.1 参数
- 函数中有两种参数:
形参
,定义函数时使用的参数,如:def 函数名(形参1,形参2,…)实参
,调用函数时使用的参数,如:函数名(实参1,实参2,…)在python中
实参
代表一个具体的数据,相当于变量值,而形参相当于变量名,当我们调用函数时,这个数据就会被绑定给形参,从而被函数中的代码使用,如下:
def a(r1): # r1 为形参用于接收实参的数据
print(r1)
a('阿豪') # '阿豪' 代表实参;输出结果:阿豪
b = '张三'
a(b) # b为实参,输出结果: 张三
说明:
从上面可以看到,实参
可以是变量
,也可以是一个具体的数据
,当我们调用函数时,实参的值被绑定给了形参
,并且在函数a
中可以通过形参使用这个值
- 当函数拥有多个参数时,
形参和实参的数量要相同
,不然会报错,在调用函数时,实参会从左往右依次绑定给形参
;如:
def a(r1,r2,r3):
print(r1) # 输出结果:222
print(r2) # 输出结果:333
print(r3) # 输出结果:666
a(222,333,666)
1.5.1.1 参数的分类(位置、默认、关键字、可变长度)
参数根据使用的方法和作用可以分为以下四类:
- 位置参数:形参和实参从左往右一一对应,依次绑定,我们通常使用的都是位置参数
def a(r1,r2,r3): # 从左往右依次绑定实参的值
print(r1) # 输出结果:222
print(r2) # 输出结果:333
print(r3) # 输出结果:666
a(222,333,666)
- 默认参数:定义函数括号内
形参=默认值
,给形参提前绑定默认值,若调用函数时,形参没有对应的实参赋值,那么形参就会使用默认值,若有对应的实参赋值,那么就以实参的值为主
def a(r1=000): # 给形参绑定默认值
print(r1)
a(222) # 有对应实参绑定给形参,输出结果:222
a() # 没有对应的实参绑定给形参,使用默认值,输出结果:000
- 关键字参数:调用函数括号内
形参名=实参值
,在函数调用时,可以将实参值绑定给指定的形参,这样实参和形参的位置就不用一一对应,就可以得到想要的值
def a(r1,r3,r2): # 可以随意变更顺序
print(r1) # 输出结果:666
print(r2) # 输出结果:0
print(r3) # 输出结果:11
a(r2=00,r3=11,r1=666) # 通过形参名指定绑定的实参值
注意:
上面的几种参数,形参和实参的数量
必须保持一致,他们之间互相对应,不然会报错
- 可变长度参数:在调用函数括号内使用,前面几种参数,一个形参只能接受一个实参,当我们需要
将多个实参绑定给一个形参时
,就需要用到可变长度参数了;一般分为两种,如下:
- 用法1:
*形参
,为了方便我们称这个参数为args,如:*args
作用:接受多个默认参数,组成一个元组
def a(*args): # 接收所有的实参,组成一个元组
print(args) # 输出结果:(111, 555, 666)
a(111,555,666)
- 用法2 :
**形参
,为了方便我们称这个参数为kwargs,如:**kwargs
作用:接受多个关键字参数,组成一个字典
def test(**kwargs): # 接受所有关键字参数,组成字典
print(kwargs) # 输出结果:{'a': 111, 'b': 555, 'c': 666}
test(a=111,b=555,c=666)
注意:
args 和 kwargs
只是一个名字,为了区分,重点是名字前面的 *
号;名称可以随意更改,如:*r1 ,**r2
- 用法3:
(*args,**kwargs )
将两种用法结合一起使用,表示可以接受任意多个,任意形式
的实参
def test(*args,**kwargs):
print(args)
print(kwargs)
test(13,666,a='阿豪',b='我爱你') # 默认参数和关键字参数分别被 *args和**kwargs接收,组成元组和字典
test() # 没有任何参数,*args和**kwargs默认会返回 空元组和空字典
输出结果:
(13, 666)
{'a': '阿豪', 'b': '我爱你'}
()
{}
- 拓展点 :用处不大
1、在调用函数括号内,使用:*列表
或*元组
,表示将元组或列表中的元素依次绑定给形参
def test(a,b):
print(a,b)
test(*[55,66]) # 将列表中的元素依次绑定给形参,要一一对应
test(*(11,22)) # 将元组中的元素依次绑定给形参,要一一对应
输出结果:
55 66
11 22
2、在调用函数括号内,使用:**字典
,表示将字典中的值绑定给指定的形参,键的名字就是形参的名字,且键必须为字符串类型
def test(b,a):
print(a,b)
test(**{'a':66,'b':'哈哈'}) # 字典中的键就是对应的形参,并将值绑定给这个形参
输出结果:
66 哈哈
1.5.1.2 参数的书写顺序
- 定义函数括号内,从左往右依次是:
位置参数,默认参数,*args,**kwargs
- 调用函数括号内,从左往右依次是:
位置参数,关键字参数
1.5.2 关键字:return
return
只会出现在函数内,它的作用有很多,如下:
- 在函数中,只要执行到
return
,立即退出这个函数
案例1:
def test():
print(666)
return # 直接退出程序,不执行后面的代码
print('哈哈') # 不会输出
test() # 输出结果:666
案例2:
def test():
while 1:
while 1:
while 1:
print(666)
return # 直接退出函数,不会陷入死循环
test() # 输出结果:666
说明:
从上面 案例2
可以看出,return
在函数中的优先级是最高的,只要执行就会退出函数
,尽管在多个死循环
内,同样可以直接退出函数;而像break
只能退出单个循环,无法同时退出多个循环,当然两者的使用场景是不同的,return是用于退出函数,break用于退出循环
;大家不要混淆了
- 语法格式:
return 返回值
- 调用函数后,执行函数中的代码,并将返回值会传给函数对象,通过
print可以将其打印出来
,若没有写返回值,默认为 None
;且返回值可以为任意数据类型
案例1:
def test():
print(666)
return '啦啦啦' # 有返回值,打印输出返回值
a = test()
print(a)
输出结果:
666
啦啦啦
案例2:
def test():
print(666)
return # 没有返回值,输出 None,不写 return 结果同样是 None
a = test()
print(a)
输出结果:
666
None
return
后面可以跟多个返回值,用逗号隔开;格式:return 返回值1,返回值2,..
当有多个返回值时,也必须有多个变量对应的进行绑定,才能打印出来,若不用变量接收,直接打印,得到的是一个元组
def test():
return 66,'哈哈',[1,2,3],{'姓名':'阿豪','年龄':18}
print(test()) # 直接打印,得到元组
a,b,c,d = test() # 绑定变量,与返回值一一对应
print(a,b,c,d)
输出结果:
(66, '哈哈', [1, 2, 3], {'姓名': '阿豪', '年龄': 18})
66 哈哈 [1, 2, 3] {'姓名': '阿豪', '年龄': 18}
总结:
每个函数都有返回值,不写则默认是 None,否则就以写的值为主;且返回值需要打印出来才能看到