10. 函数

news/2024/12/1 11:34:47/

一、什么是函数

  函数也是对象,对象是内存中专门用来存储数据的一块区域。函数可以用来保存一些可执行代码的,并且可以在需要时,对这些语句进行多次调用。

二、创建函数

  创建函数也称为定义函数。我们可以使用 def 关键字来定义函数,它的语法格式如下:

python">def 函数名(参数列表):# 函数体pass
  • 函数名:按照命名规则起个名字,在 Python 中建议小写加下划线的方式;
  • 函数体:整个函数真正要执行的代码,一般函数体前面缩进缩进四个空格(缩进统一即可);
  • 参数列表:专门用来存储调用时传递给函数的数据;
python">def say_hello():print("This is a function!")print("hello world!")

定义好的函数并不会执行,你需要调用它,它才能执行里面的代码;

三、函数的调用

  函数的调用也就是执行函数。调用函数的语法格式如下:

python">函数名(参数列表)
python">say_hello()

同一个函数只需要定义一次,但是可以调用多次;

四、函数的参数

4.1、形参与实参

  在定义函数时,可以在函数名后的 () 中定义数量不等的 形参,多个使用之间使用逗号 , 隔开。形参也称 形式参数,定义形参就相当于在函数内部声明了变量,但是并不赋值。如果函数定义时,指定了形参,那么在调用函数传入的值称为 实际参数,简称 形参

  在调用阶段,实参会绑定给对应的形参,简单来说,有几个形参就要传几个实参。这种绑定关系只能在函数体内使用。实参和形参的绑定关系在函数调用时生效,函数调用结束后解除绑定关系。

python"># 定义函数时,指定形参
def sum(a, b):print(a, ' + ', b, ' = ', (a + b))# 调用函数时,传递实参
sum(10,20)

  如果实参的个数与形参的个数不匹配会报以下的错误:

python">TypeError: sum() takes 2 positional arguments but 3 were given  
TypeError: sum() missing 1 required positional argument: 'b' 

4.2、参数传递的方式

  实参的传递方式有 2 种,一种是 位置参数,另一种是 关键字参数

  位置参数 就是对应位置的实参赋值给对应位置的形参。即第一个实参赋值给第一个形参,第二个实参赋值给第二个实参,以此类推。

python">def showInfo(name, age, gender):print("name: ", name, ", age: ", age, ", gender: ", gender)showInfo("Sakura", 10, '女')

  关键字参数 可以不按照形参定义的顺序去传递,而直接根据参数名去传递参数。

python">def showInfo(name, age, gender):print("name: ", name, ", age: ", age, ", gender: ", gender)showInfo(name = "Sakura", gender = '女', age = 10)

  按照关键字传值的时候,如果形参名不存在,会报以下的错误:

python">TypeError: showInfo() got an unexpected keyword argument 'sex'

  位置参数可以和关键字参数混合使用。

python">def showInfo(name = "unknown", age = 0, gender = "secrecy"):print("name: ", name, ", age: ",age, ", gender: ", gender)showInfo("Sakura",gender = '女', age = 10)

  混合使用位置参数和关键字参数时,必须将位置参数写在前面。否则会报以下错误:

python">SyntaxError: positional argument follows keyword argument

  在函数调用时,我们不能通过位置参数和关键字参数同时给一个形参赋多次值,否则会报以下错误:

python">TypeError: showInfo() got multiple values for argument 'name'

4.3、默认参数

  定义形参时,我们可以为形参指定默认值。指定默认值 后,如果用户传递参数,则默认值没有任何作用;如果用户没有传递参数,则默认值就会生效。

python">def showInfo(name = "unknown", age = 0):print("name: ", name, ", age: ",age)showInfo("Sakura")

  位置形参必须在默认形参的左边,否则会报以下错误:

python">SyntaxError: non-default argument follows default argument

  虽然形参的默认值可以指定为任意的数据类型,但是不推荐使用 可变类型

python">names = ["Sakura","Mikoto"]def printName(name=names):for name in names:print(name,end='\t')print()printName()names.append("Shana")printName()

4.4、不定长参数

  不定长参数(可变参数)指的是在调用函数时,传入的值(实参)的个数不确定。在定义函数时,我们可以在形参前面加上一个 * ,这样这个形参将会获得所有的实参。它会将所有的实参保存到一个元组中。

python"># *nums会接受所有的位置参数,并且会将这些参数统一保存到一个元组中
def sum(*nums):print("nums = ", nums, "type: ", type(nums))result = 0for n in nums:result += nprint(result,'\n')sum()
sum(1,2)
sum(1,2,3)

  在 * 号的形参只能有一个,带 * 号的参数也可以和其它参数配合使用。

python"># 第一个参数给num1,第二个参数给num2,剩下的都保存到nums的元组中
def sum(num1, num2, *nums):print("num1: ", num1)print("num2: ", num2)print("nums: ", nums, "type: ", type(nums))result = 0for n in nums:result += nprint(result, '\n')sum(1,2)
sum(1,2,3)
sum(1,2,3,4)
sum(1,2,3,4,5)

  可变参数可以不写在最后,但是,带 * 后的所有参数,必须以关键字参数的形式传递。

python"># 第一个位置参数给num1,剩下的位置参数给nums的元组,num2必须使用关键字参数
def sum(num1, *nums, num2):print("num1: ", num1)print("num2: ", num2)print("nums: ", nums, "type: ", type(nums),'\n')sum(1,2,num2 = 3)
sum(1,2,3,num2 = 4)
sum(1,2,3,4,num2 = 5)
python"># 所有的位置参数后给nums,num1和num2必须使用关键字参数
def sum(*nums, num1, num2):print("num1: ", num1)print("num2: ", num2)print("nums: ", nums, "type: ", type(nums),'\n')sum(1,num1 =2,num2 =3)
sum(1,2,num2 = 3,num1 = 4)
sum(1,2,3,num1 = 4,num2 = 5)

  如果在形参的开头直接写一个 *,则要求我们的所有参数必须以关键字参数的形式传递。

python">def sum(*, num1=10, num2=20, num3):print("num1: ", num1)print("num2: ", num2)print("num3: ", num3)print()sum(num3=30)
sum(num1=11, num2=22,num3=33)
sum(num2=10,num3=10)

  * 形参只能接受位置参数,而不能接受关键字参数。但我们可以使用 ** 形参接受其它的关键字参数,它会将这些参数统一保存在字典中,字典的 key 就是参数的名字,字典的 value 就是参数的值。

python">def sum(**nums):print("nums: ", nums, ", type: ", type(nums))sum(num1 =1,num2 = 2, num3 = 3)

  ** 形参只能有一个,并且必须写在所有参数的最后。

python">def sum(num1, num2, **nums):print("num1: ", num1)print("num2: ", num2)print("nums: ", nums, ", type: ", type(nums))sum(num1 =1,num2 = 2, num3 = 3, num4 = 4)

4.5、参数的解包

  传递实参时,也可以在序列类型的参数前添加 * 号,这样它会自动将序列中的元素一次作为参数传递。这里要求序列中元素的个数必须和形参中的个数一致。

python">def fun(num1, num2, num3):print("num1: ", num1)print("num2: ", num2)print("num3: ", num3)t = (10,20,30)
fun(*t)print()l = [10,20,30]
fun(*l)

  我们还可以通过 ** 对字典进行解包。字典的 key 要与函数的形参对应。

python">def fun(num1, num2, num3):print("num1: ", num1)print("num2: ", num2)print("num3: ", num3)d = {"num1":10, "num2":20, "num3":30}
fun(**d)

4.6、实参的类型

  函数在调用时,解析器不会检查实参的类型,实参可以是任意类型的对象。

python">def showInfo(arg):print("arg: ", arg)showInfo("Sakura")
showInfo(True)
showInfo(123)
showInfo(None)
showInfo([1,2,3])

  在函数中对形参进行重新赋值,不会影响到其它的变量。

python">def fun(arg):arg = 30print("arg: ", arg, "id: ",id(arg))c = 10
fun(c)
print('c: ', c, "id: ", id(c))

  但是,如果形参指向的是一个对象,当我们通过形参去修改对象时,会影响到所有指向该对象的变量。

python">def fun(arg):arg[0] = 30print('arg: ', arg, 'id: ',id(arg))c = [1,2,3]
fun(c)
print('c: ', c, 'id: ', id(c))

  此时,我们可以传递实参的一个副本。

python">def fun(arg):arg[0] = 30print("arg: ", arg, "id: ",id(arg))c = [1,2,3]
# fun(c.copy())
fun(c[:])
print('c: ', c, "id: ", id(c))

函数的参数默认传递的是 形参的引用

五、函数的返回值

  返回值 就是函数执行以后返回的结果。我们可以通过 return 来指定函数的返回值。我们可以直接使用函数的返回值,也可以通过一个变量来接受函数的返回值。return 后面跟什么值,函数就会返回什么值。return 后面可以跟任意对象,返回值甚至可以是一个函数。

python">def sum(*nums):print("nums = ", nums, "type: ", type(nums))result = 0for n in nums:result += nprint(result,'\n')sum()
sum(1,2)
sum(1,2,3)

  如果仅仅写一个 return 或不写 return,则相当于 return None。

python">def fun():passprint(fun())
python">def fun():returnprint(fun())

  在函数中,return 后的代码都不会执行。return 一旦执行,函数自动结束。

python">def fun():print("hello")returnprint("world")print(fun())

  我们还可以使用都好分割开多个返回值,此时会被 return 返回为元组的形式。

python">def add(a,b):return a,b,a+bresult = add(10,20)
print(result)
print(type(result))

函数名 是函数对象,打印函数名实际是在打印函数对象;

函数名() 是在调用函数,打印函数名()实际上是在打印函数的返回值;

return 是函数结束的标志,即函数体代码一旦运行到 return 会立刻终止函数的运行,并且会将 return 后的指当作本次运行的结果返回。

六、文档字符串

  我们可以通过 help() 函数查询 python 中函数的用法。help() 函数是 python 内置的一个函数,它的使用语法格式如下:help(函数对象)。

python">help(print)

  在定义函数时,我们可以在函数内部编写文档字符串,文档字符串 就是函数的说明。当我们编写了文档字符串时,就可以通过 help() 函数来查看函数的说明。文档字符串其实就是直接在函数的第一行写一个字符串,一般我们会使用三重引号,这样可以写多行。

python">def sum(num1:int=0, num2:int=0,*nums:int):"""这是一个加法函数@param num1 接收第一个加数@param num2 接收第二个加数@param *nums 可以接受任意多个参数@return result 该函数返回相加的结果"""result = 0for n in nums:result += nhelp(sum)

七、作用域

  作用域指的是变量生效的区域。在 python 中一共有 2 中作用域。一种是 全局作用域,另一种是 函数作用域

  全局作用域 在程序执行时创建,在程序结束时销毁。所有函数以外的区域都是全局作用域。在全局作用域中定义的变量,都属于全局变量,全局变量可以在程序的任意位置被访问。

  函数作用域 在函数调用时创建,在调用结束时销毁。函数每调用一次,就会产生一个新的函数作用域。在函数中作用域中定义的变量,都是局部变量,它只能在函数内部被访问。

python">b = 20def fun():# a定义在函数内部,所以它的作用域就是函数内部,函数外部无法访问a = 10print("函数内部:a = ", a)print("函数内部:b = ", b)fun()
print("函数外部:b = ", b)

  当我们使用一个变量时,会优先在当前作用域中寻找变量。如果有则使用,如果没有则继续去上一级作用域中去寻找。如果上一级作用域中有则使用,如果依然没有则继续去上级作用域中寻找,以此类推。

python">def fun1():a = 10b = 10print("fun1中的a:", a)print("fun1中的b:", b)def fun2():a = 20print("fun2中的a:", a)print("fun2中的b:", b)fun2()fun1()

  如果直至找到全局作用域,依然也没有找到,则会抛出异常:

python">NameError: name 'c' is not defined

  在函数中为变量赋值时,默认都是为局部变量赋值。如果希望在函数内部修改全局变量,则需要使用 global 关键字来声明变量。

python">a = 10
b = 10def fun():# 在函数中为变量赋值时,默认都是为局部变量赋值a = 20# 如果希望在函数内部修改全局变量,则需要使用 global 关键字来声明变量global b# 修改全局变量b = 30print("函数内部:a = ", a)print("函数内部:b = ", b)fun()
print("函数外部:a = ", a)
print("函数外部:b = ", b)

建议全局变量大写,局部变量小写;

八、类型提示

  在 Python 3.5 以上的版本函数支持类型提示功能。

python">def 函数名(形参:形参提示性信息) -> 返回值提示信息:...
python">def showInfo(name:str,age:int=0) -> dict:print(f"name:{name},age:{age}")return {"name":name,"age":age}result = showInfo("Sakura",10)
print(result)
result = showInfo("Sakura")
print(result)# 可以通过__annotations__查看函数的提示信息
print(showInfo.__annotations__)

九、函数递归

  递归简单理解就是自己引用自己。递归式函数就是在函数中自动调用自己(直接或间接调用函数本身)。递归是解决问题的一种方式,它和循环很像。它的整体思想是,将一个大的问题分解为一个个的小问题,直到问题无法分解时,再去解决问题。

  递归式函数的两个要件:

  1. 基线条件
    • 问题可以被分解为的最小问题,当满足基线条件时,递归就不在执行了
  2. 递归条件
    • 将问题继续分解的条件
python">def factorial(num):# 基线条件,判断num是否为1,如果为1则此时不能再继续递归if num == 1:return 1return num * factorial(num-1)ressult = factorial(10)
print(ressult)

十、内建函数

  Python 解释器运行时,会自动加载很多的常用的变量、函数以及类,这些就是内建功能或者数据,我们把自动导入的函数称之为 内建函数。我们可以通过 dir(__builtin__) 来查看 Python 解释器运行时自动加载的数据。

【1】、range() 函数

python">range(start, stop[, step])

  range() 可以用来生成一个自然数的序列,它有三个参数,第一个参数是 起始位置,可以省略,默认是 0,第二个参数是 结束位置,第三个参数是 步长,也可以省略,默认是 1。

  range() 函数返回一个 range 对象,是一个可迭代的对象,可以配合 for 或 next() 等使用。如果想要得到列表,可通过 list() 函数。

python">a = range(5)
print(a)
print(type(a))
print(list(a))

【2】、map() 函数

python">map(function, iterable, *iterables)

  map() 函数会根据提供 function 指向的函数对指定的序列 iterable 做映射。参数序列中的每一个元素分别调用 function() 函数,将每次 function() 函数的返回值,存放到序列中当作最后的结果。

python">a = map(lambda x: x**2, range(1,6))
print(a)
print(type(a))for item in a:print(item)
python">a = map(lambda x, y: x+y, [1, 2, 3], (4, 5, 6))
print(a)
print(type(a))for item in a:print(item)

【3】、filter() 函数

python">filter(function, iterable)

  filter() 函数会对序列 iterable 中的每个元素调用 function 指向的函数执行过滤操作。在每次执行时,结果为 True 的序列元素存储到结果中。

python">a = filter(lambda x : x%2, range(1,6))
print(a)
print(type(a))for item in a:print(item)

十一、函数对象

  在 Python 中,函数是一等对象,它具有以下特点:① 对象是在运行时创建的; ② 能赋值给变量或作为数据结构中的元素; ③ 能作为参数传递; ④ 能作为返回值返回;

python">def func():print("func()函数执行了")# 可以将函数赋值给一个变量
f = func
print(f)
print(func)# 通过变量调用函数
f()
python">def func():print("func()函数执行了")# 可以把函数当作函数的参数传入
def fun(f):print(f)f()fun(func)
python">def func():print("func()函数执行了")# 可以把函数当作函数的返回值返回
def fun():return funcres = fun()
print(res)
res()

十二、高阶函数

  高阶函数至少要符合以下两个特点中的一个:① 接收一个或多个函数作为参数; ② 将函数作为返回值返回;

  当我们使用一个函数作为参数时,实际上是将指定的代码传递进了目标函数。

python">def filter(list, fun):new_list = []for n in list:if fun(n):new_list.append(n)return new_listdef IsEven(num):return num %2 == 0def IsGreater5(num):return num > 5list = [x for x in range(11)]new_list = filter(list,IsEven)
print(new_list)new_list = filter(list,IsGreater5)
print(new_list)

十三、匿名函数

  匿名函数也称为 lambda 函数表达式,lambda 表达式专门用于创建一些简单的函数,它是函数创建的又一种方式。它的语法格式如下:

python">lambda 参数列表 : 返回值

  我们可以通过如下方法调用 lambda 函数表达式:

python">(lambda 形参列表 : 返回值)(实参列表)
python">print(lambda a, b : a + b)
print((lambda a, b : a + b)(10, 20))

我们也可以将一个匿名函数赋值给变量。

python">def filter(list, fun):new_list = []for n in list:if fun(n):new_list.append(n)return new_listlist = [x for x in range(11)]new_list = filter(list, lambda num : num % 2 == 0)
print(new_list)new_list = filter(list, lambda num : num > 5)
print(new_list)

匿名函数一般都是作为参数使用;

如果匿名函数不需要形参,可以书写如下格式:lambda : 表达式

匿名函数默认有 return;


http://www.ppmy.cn/news/1551474.html

相关文章

day05 Linux bash核心及目录命令

1. 手动配置IP nmtui: NetworkManager text user interface,网络管理文本用户界面,用于配置和控制 NetworkManager 的工具。 手动添加网卡信息 223.5.5.5是阿里云的DNS服务器地址 202.106.0.20是在北京,中国联通的DNS服务器地址 systemctl…

阿里云ECS服务器磁盘空间不足的几个文件

查看磁盘空间命令: df -h /mnt 清零 echo >nohup.out 磁盘空间不足的文件列表: 一、nohup.out:来自"nohup java -jar service.jar &"命令产生的文件,位置在服务jar所在目录 二、access.log:位于…

【设计模式】1. 构建器模式(Builder Pattern)是一种创建型设计模式

构建器模式(Builder Pattern)是一种创建型设计模式,用于分步骤构建复杂对象,同时允许按照不同的需求生成不同的表示。该模式将对象的构建过程与其表示分离,使得相同的构建过程可以创建不同的对象。 核心思想 构建器模…

javaweb Day11

Maven高级 1.分模块设计

服务器挖矿

文章目录 一、确定挖矿进程并停止二、查找并清除挖矿相关文件三、检查并修复系统漏洞四、加强安全防护 一、确定挖矿进程并停止 查找挖矿进程 在Linux系统中,可以使用命令如top或htop来查看系统资源占用情况。挖矿程序通常会占用大量的CPU或GPU资源。例如&#xff…

VTK中对于相机camera的设置

1. 相机的核心属性 在 VTK 中,vtkCamera 的核心属性有默认值。如果你不设置这些属性,相机会使用默认值来渲染场景。 Position(默认值:(0, 0, 1)): 默认情况下,相机位于 Z 轴正方向的 (0, 0, 1)…

课题组自主发展了哪些CMAQ模式预报相关的改进技术?

空气污染问题日益受到各级政府以及社会公众的高度重视,从实时的数据监测公布到空气质量数值预报及预报产品的发布,我国在空气质量监测和预报方面取得了一定进展。随着计算机技术的高速发展、空气污染监测手段的提高和人们对大气物理化学过程认识的深入&a…

如何通过ChatGPT提高自己的编程水平

在编程学习的过程中,开发者往往会遇到各种各样的技术难题和学习瓶颈。传统的学习方法依赖书籍、教程、视频等,但随着技术的不断发展,AI助手的崛起为编程学习带来了全新的机遇。ChatGPT,作为一种强大的自然语言处理工具&#xff0c…