Python学习笔记(2-3):基础知识之函数
文章导读
- 课程难度:★★☆☆☆
- 预计学习时间:1小时
- 简介:本节主要讲解了Python函数相关的知识,包括:(1)自定义函数的语法格式及注意要点;(2)函数的三种传参方式及返回值的设置;(3)几个重要的补充内容;
(4)三个基础函数的使用:格式转换函数、range()函数和print()函数
- 重点涉及的函数和内容:(1)自定义函数的格式;(2)函数的作用域问题;(3)python函数没有重载;(4)int()、float()、str()函数分别将数据转换成整型、浮点型和字符串型;
(5)range()函数的基础用法及其与for循环相结合以遍历各种元素;(6)print()函数的使用
一、自定义函数
定义函数,最重要的是用来代码重用和模块化。
自定义函数的格式如下:
def 函数名(参数):
函数体
return 返回值
定义一个函数需要定义函数的函数名和函数体,其基本规则如下:
- 以
def
关键字作为定义函数的声明。 - 给出函数名。
- 以一个圆括号指示所有的参数(也可以没有参数),参数之间以逗号
,
分隔。 - 最后以冒号
:
结束。 - 最后在新行开始编写函数的具体内容,即函数体,函数体的内容需要缩进。
- 函数的默认参数。默认参数是指一个参数的默认值,函数在调用时可以不传递这个参数,直接使用定义时给出的默认值。在函数定义的时候,不能有带默认值的参数出现在无默认值参数前面的情况。
- 函数的返回值,用
return
关键字标识函数最终的运行结果,返回值用逗号分隔。一个函数可以有多个返回值,也可以没有返回值。 - 定义和调用函数时,定义参数时允许换行,传入的最后一个参数后面可以带逗号
,
,像列表一样,这个逗号之后没有值会被自动忽略
我们依照最后一点定义一个函数,如下:
def function(
a = 0,
b = [1, 2],
c = '567',
):
a += 100
b = [None]
c = len(c)
print(a, b, c)
# 调用这个函数:
a = 20
function(
a = 20,
b = [0, 1, 2],
c = (1, 4, 7, 10),
)
这种函数的写法,虽然比较占行,但是写起来函数定义和调用参数较为清晰,可以在一些需要传递参数比较多的程序里常使用。当然,也不是每一个数据都要换一个行,根据自己的需要把握即可。
二、函数的参数和返回值
1、函数的传参方式
我们利用几个调用过程讲解向函数传递参数的几种方式:
- 利用位置参数传参
这种方式不需要写出函数的各个参数的名称,但各个参数需要按照顺序,且一一对应:
print(function(4, 1))
print(function(4))
- 利用关键字参数传参
这种方式需要写出各个参数的名称,各参数不需要严格按照顺序:
print(function(x = 4, y = 1))
print(function(y = 4, x = 1))
- 利用位置参数和关键字参数相结合来传参
这种方式中位置参数必须在前面,自从出现了第一个关键字参数后,不能再有位置参数
print(function(4, y = 1))
这里提出两个错误的情况:
print(function(y = 2)) # 没有给出x的参数值
print(function(y = 2, 0)) # 在关键字参数之后出现了位置参数
2、函数的返回值
函数可以有多个返回值,也可以仅有一个,也可以是没有返回值。我们把函数复制几份,分别根据返回值数目的不同赋予不同的名称,讲解一下设置返回值部分的规则:
def function_1return(x, y = 3):
Dif = x - y
Prod = x * y
return Dif
def function_2return(x, y = 3):
Dif = x - y
Prod = x * y
return Dif, Prod
def function_3return(x, y = 3):
Dif = x - y
Prod = x * y
return Dif, Prod, x
def function_zeroreturn(x, y = 3):
Dif = x - y
Prod = x * y
return # 没有返回值,但显式使用了return关键字
def function_noreturn(x, y = 3):
Dif = x - y
Prod = x * y # 没有返回值,也不用return声明函数的结束
(1)带了返回值的结果,在运行时将全部返回。对于没有返回值的结果,无论带不带return
语句,其函数的运行结果都是None
。执行如下代码的输出结果如下:
print(function_1return(2, 3))
print(function_2return(2, 3))
print(function_3return(2, 3))
print(function_zeroreturn(2, 3))
print(function_noreturn(2, 3))
输出结果如下:
-1
(-1, 6)
(-1, 6, 2)
None
None
(2)对于有多个返回值的函数,我们可以定义与返回值数目相等的变量,去接收每一个返回值,接收返回值的过程类似于多个参数的统一赋值:
a = function_1return(2, 3)
b1, b2 = function_2return(2, 3)
c1, c2, c3 = function_3return(2, 3)
print(a)
print(b1, b2)
print(c1, c2, c3)
输出结果如下:
-1
-1 6
-1 6 2
或者,我们也可以定义一个唯一的变量接收所有这些返回值,此时被赋值的变量是一个元组形式的数据,包含了多个值。执行如下代码:
a = function_1return(2, 3)
b = function_2return(2, 3)
c = function_3return(2, 3)
print(a, b, c)
输出结果如下:
-1 (-1, 6) (-1, 6, 2)
直接定义与返回值等数目的变量接收返回值。也可以理解成把返回值的元组给自动拆包了,分给了多个变量。关于元组拆包的内容,也会在下次课提到。
三、补充知识
刚刚讲解了函数在定义、调用和返回值上的一些理论知识,在此,补充几件函数部分重要的内容:
1、函数的作用域
需要注意的是,函数体内部的变量,并不能在函数外部调用。具体示例如下:
Dif = 0
def function(x, y = 3):
Dif = x - y
Prod = x * y
return Dif, Prod
print(function(2, 3))
print(Dif)
输出结果如下:
102 [None] 3
0
从上面的例子中可以看出,Dif并没有变化,这就代表我们传递的参数不会被函数体内的操作而更改。如果需要将外部的变量引入函数中,一种做法是声明函数内的变量为全局变量。这时,我们可以引入global
关键字,将函数内引用/定义的某个变量声明为全局变量。通过程序的代码和输出简单观察效果,此时作为None
值的a被修改成空列表:
a = None
def bind_a_variable():
global a
a = []
bind_a_variable()
print(a)
输出结果如下:
[]
但是如果往函数里传入列表等数据结构的参数,在函数里修改这个参数,可能会影响原值。
2、python的函数没有重载
如果我们先后定义两个同名函数,后面的函数会直接覆盖前面的。我们试着调用之前的函数,结果会报错:例如:
def fun(x, y):
print(3)
def fun(x):
print(4)
输出结果如下:
fun(2, 3) # 报错
fun(2)
这一点请大家注意,比如不要之前定义了处理列名的函数colname,后面又定义了自己要保留的列名colname,这个列名就把函数给覆盖掉了。
3、函数的嵌套调用
这里要强调函数嵌套调用的时候,一个函数作为另一个函数的参数时,这个函数也会被执行一次。我们定义两个函数,并予以调用:
def fun1(x):
print('fun1 called')
return x + 4
def fun2(x, y):
print('fun2 called')
return x + y
x , y = 3, 4
print(fun1(fun2(x, y)))
输出结果如下:
fun2 called
fun1 called
11
fun1调用了fun2的运算结果,因此为了计算fun2的调用结果,fun2会被调用一次。再拿到fun2的运算结果(也即返回值)之后,fun1开始调用并返回结果。最后,我们把fun1的运算结果,通过print
函数打印在屏幕上。
4、函数的递归调用
函数的递归调用即一个函数直接或间接调用自身的过程,看如下的例子:
def fun_recur(x, t):
if x > 1:
x -= 1
t += 10
return fun_recur(x, t)
else:
return t
fun_recur(3.2, 25)
输出结果如下:
55
上述例子产出最终的结果55,实际上包含了如下的过程:
x = 3.2,t自加10,进入一重递归
x = 2.2,t自加10
x = 1.2,t自加10
x = 0.2,进入else语句,返回值为t(55),之后先后跳出之前的三次递归过程,返回结果。
递归函数在将一个大问题能转化成反复调用的小问题时,很省代码量,但是递归本身的效率相比普通循环要低,因此在使用的时候建议有所取舍。
5、函数作为函数调用的参数,作为值传递的参数
在python中,所有的元素都是对象,函数也能作为函数本身调用的对象和值传递的参数,例如如下的代码块,利用函数作为参数传递的方式,实现当x满足某个条件时,返回x+y,而这个条件通过函数对象funx进行描述:
def fun(x, y, funx):
if funx(x) < 0:
return x
else:
return x + y
def funx(x):
return x - 50
print(fun(40, 30, funx))
print(fun(80, 30, funx))
输出结果如下:
40
110
一个函数就像各种其他参数一样,也能作为函数的参数,请注意它的启发性。
四、函数举例
1、格式转换函数
它传入一个参数,即将一个类型的数值转换为另一个类型。我们最常用的就是整型、浮点型和字符串的互转,我们只需要将待转格式的参数传入相应的函数即可:
int()函数能将浮点型或可以看做整数的数据转成整数,是截断,即删去小数位。
float()函数能将整或可以看做数值型(整数小数均可)的数据转成浮点数。
str()函数能将各类数字转成对应的字符串。
print(int(3.5))
print(int('10'))
print(float(4))
print(float('3.5'))
print(str(1.2) + 'test') # 只有字符串能通过加号拼接其他字符串,表明转换成功
输出结果如下:
3
10
4.0
3.5
1.2test
2、range()函数
range
函数的语法:
range(start, stop[, step])
- start:表示初始值
- stop:终止值(不包括)
- step:步长
它有三种传参使用的情况:
- 传入三个参数:分别传入起始值、终止值和步长。它会返回一个
range
对象,我们需要用list
函数把它转换成列表来查看它的值,具体示例如下:
print(range(2, 20, 4))
print(list(range(2, 20, 4)))
输出结果如下:
range(2, 20, 4)
[2, 6, 10, 14, 18]
当步长为负值时:
print(list(range(10, 1, -2)))
输出结果如下:
[10, 8, 6, 4, 2]
这里来看两种比较特殊的情况,第一种是,步长已经超过了整个start-stop的跨度,此时返回的range
转成列表后只有start
一个元素:
print(list(range(1, 10, 100)))
输出结果如下:
[1]
第二种是,步长和start-stop变化的方向彻底相反(相当于定义错了),此时返回的range
转成列表后是空列表:
print(list(range(1, 10, -2)))
输出结果如下:
[]
- 传入两个参数:即
start
和stop
,此时step
取默认值1:
print(list(range(2, 5)))
输出结果如下:
[2, 3, 4]
- 传入一个参数:只传递一个参数
stop
,此时默认值start = 0
,step = 1
:
print(list(range(5)))
输出结果如下:
[0, 1, 2, 3, 4]
在之后的数据分析任务中,会经常使用for
循环并结合range
函数这种方式来访问各种数组、列表、数据框等数据结构中的元素值,以列表为例:
listtmp = ['12', '23', '34', '45', '56']
for i in range(len(listtmp)):
print(listtmp[i])
输出结果如下:
12
23
34
45
56
补充一点,内置的range
函数传递的参数必须是整数,否则会报错。
3、print()函数
print
函数在这里细讲的原因它可以输出我们能接触到的几乎所有对象,我们只讲输出一般的数值,以及将之整理成格式化字符串结果的那种功能。
(1) 它可以接收多个待输出的值,不同参数类型可以不一样,参数之间用逗号分隔(两个逗号之间不能没有值),这是它的基础用法:
print('alpha', 1, 'beta', 2, ['listvalue1', 'listvalue2', 2.5])
输出结果如下:
alpha 1 beta 2 ['listvalue1', 'listvalue2', 2.5]
(2)关于它的两个参数:一个是输出参数之间的分隔符sep
,默认参数是’ ',即一个空格,我们可以改成自己愿意的值,当然必须是空或者是字符串。具体代码及输出结果如下:
a = 10
print('alpha', 1, 'beta', 2, ['listvalue1', 'listvalue2', 2.5], sep = ' _%_ ')
print('alpha', 1, 'beta', 2, ['listvalue1', 'listvalue2', 2.5], sep = a) # 报错1,sep错误
alpha _%_ 1 _%_ beta _%_ 2 _%_ ['listvalue1', 'listvalue2', 2.5]
报错1【TypeError: sep must be None or a string, not list】
第二个参数是在整个输出末尾的符号end
,默认是换行符’\n’,这么做表示在默认参数下,每次输出都自动换行,我们可以把end
改成自己需要的标识符,此时便不换行。当我们连续调用两个print
,将第一个print
的结尾换成一个字符串后,再输出下一句话时就不会换行了,如代码运行的结果所示。当然,输出if newline这句话后是会换行的,因为end
是默认值’\n’:
print('alpha', 1, 'beta', 2, ['listvalue1', 'listvalue2', 2.5], end = ' _end_ ')
print('if newline ?')
输出结果如下:
alpha 1 beta 2 ['listvalue1', 'listvalue2', 2.5] _end_ if newline ?
对于缺乏Python基础的同仁,可以通过免费专栏🔥《Python学习笔记(基础)》从零开始学习Python
结语
请始终相信“Done is better than perfect”
,不要过分追求完美,即刻行动就是最好的开始, 一个模块一个模块地积累和练习,必将有所收获。
还有其他的问题欢迎在评论区留言📝!
[版权申明] 非商业目的注明出处可自由转载,转载请标明出处!!!
博客:butterfly_701c