写给Python社群的第5课:Python 函数,真的难吗?
⛳️ 函数简介
这篇博客给大家带来的是 Python 函数,每次讲解到函数的时候,都会有很多同学掉队,其核心原因是思维的转变,在前文的几篇博客中,都是以线性思维进行说明,翻译成编程逻辑就是顺序思维,加入函数之后,顺序思维会因为函数而发生跳转,即进入函数,跳出函数的逻辑反复出现,所以初学者在学习阶段,很容易迷惑。
其实在前四篇博客中,我们已经大量使用了函数,例如 print()
输出函数,len()
获取列表长度函数,sorted()
排序函数,del()
对象删除函数。
这时在回忆一下,你在使用函数的时候无需知道函数内部的代码是如何实现,而只需要知道函数名和参数,以及函数返回的结果即可使用对应函数。
函数最基础的应用场景就是把相同的代码抽离出来,独立实现一个功能,然后反复调用!
⛳️ 函数实战
🔥 定义函数
函数是封装好的功能代码,其可以反复被调用,语法格式如下。
def 函数名([参数[,更多参数]]):
函数体
[return 返回值]
其中中括号内容都属于可选内容,如果去除这部分之后,你会发现一个精简的函数声明语法。
def 函数名():
函数体
其中 def
作为函数声明的关键字出现,函数名需要遵守命名规则,即见名知义,小括号中的参数为可选内容,其后跟英文冒号,函数体是实现函数功能的核心代码,return
语句是函数的返回值。
🔥 无参函数和带参函数
函数定义的正式学习都是从无参函数开始的,我们定义一个返回【你好】的函数。
def my_func():
return "你好"
# 函数调用
my_func()
定义函数之后,如果希望使用函数,直接采用 函数名+小括号的格式调用即可,例如上述代码的 my_func()
调用 。
无参函数是最简单的函数定义形式,在此基础上可以携带一个参数,例如下述代码。
def my_func(name):
print(name,'你好')
my_func('橡皮擦')
调用带参数的函数,需要传入参数值,即上述代码将 橡皮擦
作为 name
参数的值,传递到函数中,然后通过 print()
函数进行输出。代码还可以进行一下修改。
def my_func(name):
print(name,'你好')
my_func(name = '橡皮擦')
调用函数传递参数的之后,在小括号中指定了参数名 name
,同时为其赋值 橡皮擦
,有了该概念之后,又可以引出来函数定义时,定义多个参数的问题。
def my_func(name,age):
print(name,'你好!''你的年龄是',18)
my_func(name = '橡皮擦',age=18)
如果在调用函数时,不主动指定参数名,那默认按照参数位置进行匹配,例如下述代码。
def my_func(name,age):
print(name,'你好!''你的年龄是',18)
my_func( '橡皮擦',18)
还需要注意,在传递参数时,指定参数名,必须放在函数传递参数实参时的尾部,下述代码是错误的。
def my_func(name,age):
print(name,'你好!''你的年龄是',18)
my_func( name = '橡皮擦',18)
错误提示如下:
File "<ipython-input-8-a5a79ab3cff7>", line 4
my_func( name = '橡皮擦',18)
^
SyntaxError: positional argument follows keyword argument
错误信息为语法错误,内容是位置参数被放在了关键字参数后。
前面又出现了几个新鲜概念,第一个是实参,与之对应的概念是形参,函数在声明的时候,使用的占位参数是形参,函数调用的时候,传递的参数实际值是实参,你可以基于这两个概念,再看一下前文所涉及内容。
上面还提及了位置参数和关键字参数,在后文函数参数一节,详细给大家说明。
🔥 函数的返回值
函数的返回值属于函数可选项,即函数是可以不带返回值的,如果没有显示使用 return
设置返回值,函数在使用完毕,会默认返回 None,return
语句除了用作函数返回值的关键字,其还携带一个阻止函数继续运行的功能,即当运行时环境发现 return
关键字之后,后续代码全部忽略执行。
def my_func(name,age):
if age >=18:
return '成年'
else:
return '年轻人'
my_func('橡皮擦',18)
🔥 函数的参数
函数的参数属于函数这一节知识点中最复杂的一块了,原因是其组合形式极多,接下来为大家逐一展示。
位置参数
什么是位置参数,在传输参数的时候,形参和实参位置一一对应,顺序不能乱,例如下述代码。
def my_func(name,age):
if age >=18:
return '成年'
else:
return '年轻人'
my_func('橡皮擦',18)
如果在向函数传递值的时候,把参数位置给混淆了,即出现如下场景。
def my_func(name,age):
if age >=18:
return '成年'
else:
return '年轻人'
my_func(18,'橡皮擦')
上述代码运行会直接报错,原因就是实参位置无法对应准确。
关键字参数
关键字参数其实说的是实参位置代码的写法,即使用 参数名=值
的格式进行传递,用该方法可以防止参数传递出错,例如修改上述代码为如下内容。
def my_func(name,age):
if age >=18:
return '成年'
else:
return '年轻人'
my_func(age = 18,name = '橡皮擦')
代码立刻可以执行,即函数在调用时,指定参数名和对应值,无需考虑参数位置。
参数默认值
在函数声明的时候,可以给参数一个缺省值,这样即使调用者没有给该函数赋值,代码也可正常运行。
def my_func(name,age=19):
if age >=18:
return '成年'
else:
return '年轻人'
my_func(name = '橡皮擦')
参数默认值,可以看作带可选参数的函数定义形式。
不定长参数 *
,**
Python 允许程序员编写不定长参数,首先我们学习一下 *
的用法,在函数定义的时候,可以在形参尾部增加一个*vars
,语法格式如下所示:
def my_func(name,age,*vars):
print(name)
print(age)
print(vars)
my_func('橡皮擦',19,1,2,3,4)
运行代码,会发现输出 vars
时,会打印一个元组,将 (1,2,3,4)
都进行了打包输出。
特别注意:在定义函数时,只能有一个
*vars
,而且只能放在最右侧,所以下述声明都是错误的。
def my_func(name,age,*vars1,*vars2):
def my_func(name,*vars,age):
接下来在说明一个 **kws
参数,在函数定义的时候,可以在参数表末尾追加该形参,其表示接收任意数量的键值对,示例代码如下:
def my_func(name,age,**kws):
print(name)
print(age)
print(kws)
my_func('橡皮擦',19,s='女',g='1',bl='234')
**kws
参数也必须放在参数表最右侧,如果有 *vars
,注意它需要在 *vars
右侧,即下述格式。
def my_func(name,age,*vars,**kws):
print(name)
print(age)
print(vars)
print(kws)
my_func('橡皮擦',19,9,s='女',g='1',bl='234')
上述代码虽然简单,但是包含了所有参数格式,我们依次看一下。
橡皮擦
和19
分别匹配了参数表中的name
,age
两个形参;19
无匹配值,并且是以位置参数进行的传递,所以其被*vars
捕获;s='女
',g='1'
,bl='234'
由于其为关键字格式传递参数值,所以*vars
无法捕获,被**kws
捕获到。
肯定有同学问 *vars
和 **kws
实战中有何用途呢?直接声明参数不好吗?
注意这里的 vars 和 kws 只是普通的变量名,可以自行替换。
答案如下,当我们向函数传递元组,列表,字典的时候,就会发现其价值,请查看下述函数声明。
my_tuple = ('橡皮擦',18,'年轻','女','研究生','985/211')
def show_info(*vars):
print(vars)
show_info(my_tuple)
可以看到,在上述代码中,我们的形参表只有一个 *vars
,就可以完整的捕获整个元组,大幅度的减少了编码难度。
同样的道理,你可以尝试将字典搭配 **kws
使用,看一下是否可能精简你的 Python 代码。
🔥 函数的作用域
刚刚过去函数参数,又到了函数作用域这一难点了,作用域知识会贯穿整个 Python 生涯,由于其知识点比较隐蔽,而且被遗忘的概率极高,所以作用域一直是初学 Python 时的大挑战。
第一个要理解的知识点是作用域知识指的的变量的作用域,所有后文讨论的都是变量内容。
先来看一下全局作用域和局部作用域这两个概念,在简化一下概念,咱们首先要学习的是全局变量和局部变量。
全部变量自赋值开始,后续任何代码块都可以访问该变量,而局部变量不可以,只能在定义它的函数内部访问。
下面我们进行一下代码演示。
name = '橡皮擦' # 全局变量
def show():
print(name) # 函数内部访问
show()
print(name) # 全局访问
此时运行代码会输出两个【橡皮擦】,该内容表示 name
作为全局变量,可以在函数内部被访问到,这里会产生一个知识点,如果你希望在函数内部修改全局变量,是否可以实现。
name = '橡皮擦' # 全局变量
def show():
name = '大橡皮' # 局部变量
print(name) # 函数内部访问
show()
print(name) # 全局访问
运行代码,发现最后一行代码输出的依旧是【橡皮擦】,函数内部的重新赋值 name='大橡皮'
并未生效,函数外访问依旧是原值,如果希望在函数内部修改全局变量,需要使用关键字 global
,修改上述代码。
name = '橡皮擦' # 全局变量
def show():
global name # 关键点
name = '大橡皮' # 局部变量
print(name) # 函数内部访问
show()
print(name) # 全局访问
在函数内部使用全局变量前,增加了一个 global name
,该语句表示函数内的 name
参数是全局变量,修改之后会影响到全局。
在程序编码实战中,不建议过多的使用 global
关键字,因其会导致变量作用域发生混乱。
📢📢📢📢📢📢
💗 你正在阅读 【梦想橡皮擦】 的博客
👍 阅读完毕,可以点点小手赞一下
🌻 发现错误,直接评论区中指正吧
📆 橡皮擦的第 743 篇原创博客
- 点赞
- 收藏
- 关注作者
评论(0)