day09 函数初识
今日内容概要
- 函数初识
- 函数的定义
- 函数的调用
- 函数的返回值
- 函数的参数
函数可以封装代码,大量减少重复代码。
昨日内容回顾
文件操作
- 读
- 读文本
- 读字节
- 读的方式
- 写
- 写文本
- 写字节
光标操作
文件修改
今日内容详细
函数初识
在一开始我们就有提到,函数的作用是封装代码,大量减少重复代码,可重用性高。
我们之前写代码的方式可以说是过程式编程,有什么需求我们就写什么样的代码,一步一步写下去。之前写过的代码一旦运行过去就不会被再次运行到。
我们今天要学习的函数,其实也是一种新的编程思路,也就是函数式编程。
接下来,我们通过一个例子来初识过程式编程与函数式编程的区别。
现在有这样一个要求,不知用len()
方法,如何能够的值一个字符串s = 'alexdasb'
的长度呢?根据我们已有的知识,可以使用for循环做到:
s = 'alexdsb'
count = 0
for i in s:
count += 1
print(count)
这种方法对于我们来说已经轻而易举了。
如果此时,我们想接着求一个列表s = [1, 2, 3, 4, 5]
的长度,即便跟前面的情况很类似,但我们不得不重新写一个代码:
s = [1, 2, 3, 4, 5]
count = 0
for i in s:
count += 1
print(count)
如果再需要求一个元组s = (7, 8, 9, 10)
的长度
s = (7, 8, 9, 10)
count = 0
for i in s:
count += 1
print(count)
我不难发现,我们虽然得到了我们想要的结果,但是循环的代码是完全重复了的。如果使用函数式编程,就可以减少这样的重复:
def my_len():
count = 0
for i in s:
count += 1
print(count)
s = "alexdsb"
my_len()
s = [1,2,3,4,5,6,7,8]
my_len()
函数的定义
从上面的例子我们已经能看出来,函数的定义结构为:
def 函数名():
函数体
def
是一个关键字,声明要定义一个函数函数名
指代函数的名字,遵循变量命名的规则()
是固定结构,用来传参:
表示语句结束缩进
函数体
为函数的代码内容
函数的调用
根据前面所学到的东西,我们可以很容易地写出一个简单地输出用户输入内容的函数:
def func():
msg = input('>>>')
print(msg)
程序运行之后直接结束,并没有按照我们预想的出现让用户输入的情况。
这是因为当程序运行到def语句时,并不会立即执行函数中的内容,而是会开辟一块内存空间,将函数的内容存储到内存中。
只有当函数被调用时,函数中的内容才会被执行。函数名()
这种形式就是在调用函数。
回到上面的例子,如果我们在最后增加对函数的调用,就可以实现我们想要的效果:
func()
这种函数名()
的结构有两层含义:
- 调用函数
- 接收返回值
函数的返回
我们学过的很多方法,比如print()
、input()
等,本质上就是函数。
如果我们将print()
和input()
两个函数本身作为参数打印出来,会有什么样的效果呢?
print(print('a'))
print(input('>>>'))
输出的结果为:
a
None
>>>123
123
print和input运行后打印出来的内容有很大差别,这是因为两个函数的返回值不同。
函数中使用return
语句返回内容。return语句的基本用法为:
def func():
a = 10
return a
a = func()
print(a)
return后面可以跟Python中任意数据类型[1]
return还可以一次性返回多个数据,返回的数据以元组的形式接收:
def func():
a = 10
b = 20
return a, b
a = func()
print(a)
输出的结果是:(10, 20)
因为返回的数据是元组,我们可以通过结构的方式获取每一个值:
def func():
a = 10
b = 20
return a, b
a, b = func() # 拆包 ,解包 ,平行赋值
print(a, b)
输出的结果为:10 20
return是函数终止的标识,return能够终止函数,它后面的代码不被执行:
def func():
for i in range(10):
return i
print(1)
a = func()
print(a)
输出的结果为:0
return会将返回值返回给调用者。
函数的返回小结:
- 函数体中不写return默认返回None;写了return不写值也返回None
- return能够返回任意数据类型(Python中所有对象)
- return能够返回多个数据类型,以元组的形式接收
- return能够终止函数,其下方的代码不会被执行
- return将返回值返回给调用者
函数的参数
位置参数
我们现在写好下面这样的函数并调用:
def yue():
print("掏出手机")
print("打开微信")
print("找到附近的人")
print("聊一聊")
print("约一约")
yue()
这个函数当然会很正常地运行。而且不管我们在什么位置,只要调用这个函数,就会打印这五行内容。
但是如果有一天,我们需要换一个app,比如不用微信,改用陌陌,该如何办呢?如果在函数上改会很麻烦且不灵活。
我们就可以通过参数的方式进行自定义函数输出的内容:
def yue(app):
print("掏出手机")
print("打开", app)
print("找到附近的人")
print("聊一聊")
print("约一约")
yue('微信')
yue('陌陌')
yue('谈谈')
通过这种传入参数的方式,我们如果需要函数输出不同的内容就不需要去改变函数本身了。
我们可以一次性传入多个参数:
def yue(app,girl,age,addr): # 形参
print("掏出手机")
print(f"打开{app}")
print(f"找一位{girl},要求年龄:{age},地区:{addr}的人")
print("聊一聊")
print("约一约")
yue("微信","女孩",18,"乌克兰") # 实参 按照位置传参
在定义函数时使用的参数被称作形式参数,也称形参。在调用函数是使用的参数是实际参数,也称实参。
上面这种函数的传参方式被称作按位置传参,实参和形参需要一一对应,否则会出现参数混乱的问题。
默认参数
对于一些特殊的情况,比如某个男生很多,女生很少的班级,录入班级信息时,会经常重复输入性别为男。这时,我们可以通过设置默认参数的方法,将性别默认设定为男。当不输入参数时,函数会自动使用男作为参数。这样会节省很多时间:
def userinfo(name,age,hobby,sex="男"):
print(f"姓名:{name} 年龄:{age} 性别:{sex} 爱好:{hobby}")
userinfo("岳新力",23,"开车")
userinfo("刘柄良",60,"玩卡丁车")
userinfo("燕莹轩",16,"听音乐","女")
userinfo("苑子蒙",16,"玩游戏","女")
userinfo("王雪芹",16,"看书","女")
userinfo("瑞瑞",18,"知难而上")
需要注意的是,默认参数需要放在位置参数的后面,否则会报错。
参数的优先级为:位置参数 -- 默认参数
混合参数
位置参数和默认参数可以混合在一起使用。需要注意的是,默认参数必须都要放在位置参数的后面:
def func(a,b,c=1,d=2):
print(a,b,c,d)
func(1,3,4,5) # 实参 位置参数传递
func(a=1,b=2,c=3,d=4) # 关键字传参 (指名道姓传参)
func(1,2,d=3) # 关键字传参 (指名道姓传参)
这里有引入了一个传参的概念。当调用函数时,我们需要把参数传递给函数,这个过程被称作传参。直接把参数按照形参的位置一一对应传入的方式被称作位置传参。也可以指定形参的名字来传参,这种方法被称作关键字传参。
当存在多个默认参数,但只想修改其中少数默认参数时,就需要使用关键字传参告诉函数需要改变的是哪一个参数。
参数的总结
- 在定义函数的阶段使用的参数是形参:
- 可以单独使用位置参数,也可以单独使用默认参数,也可以混合使用
- 位置参数:必须一一对应
- 默认参数:可以不传参,可以传参,传参就是把默认的值给覆盖
- 混合使用:位置参数,默认参数
- 在调用函数的阶段使用的是实参:
- 可以单独使用位置参数,也可以单独使用关键字参数,也可以混合使用
- 位置传参:必须一一对应
- 关键字传参:指名道姓的方式进行传参
- 混合使用:位置参数,默认参数
- 将实参传递给形参的过程就是传参
事实上,return后面可以跟Python中所有的对象。 ↩︎