写给Python社群的第5课:Python 函数,真的难吗?

举报
梦想橡皮擦 发表于 2023/02/20 14:49:15 2023/02/20
【摘要】 ⛳️ 函数简介这篇博客给大家带来的是 Python 函数,每次讲解到函数的时候,都会有很多同学掉队,其核心原因是思维的转变,在前文的几篇博客中,都是以线性思维进行说明,翻译成编程逻辑就是顺序思维,加入函数之后,顺序思维会因为函数而发生跳转,即进入函数,跳出函数的逻辑反复出现,所以初学者在学习阶段,很容易迷惑。其实在前四篇博客中,我们已经大量使用了函数,例如 print() 输出函数,len...

⛳️ 函数简介

这篇博客给大家带来的是 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 分别匹配了参数表中的 nameage 两个形参;
  • 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 篇原创博客

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。