10. 函数

一、什么是函数

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

二、创建函数

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

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

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

三、函数的调用

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

函数名(参数列表)
say_hello()

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

四、函数的参数

4.1、形参与实参

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

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

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

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

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

4.2、参数传递的方式

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

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

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

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

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

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

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

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

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

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

SyntaxError: positional argument follows keyword argument

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

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

4.3、默认参数

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

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

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

SyntaxError: non-default argument follows default argument

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

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

4.4、不定长参数

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

# *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)

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

# 第一个参数给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)

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

# 第一个位置参数给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)
# 所有的位置参数后给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)

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

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 就是参数的值。

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

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

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、参数的解包

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

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 要与函数的形参对应。

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、实参的类型

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

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

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

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

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

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

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

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 后面可以跟任意对象,返回值甚至可以是一个函数。

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。

def fun():passprint(fun())
def fun():returnprint(fun())

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

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

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

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(函数对象)。

help(print)

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

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 中作用域。一种是 全局作用域,另一种是 函数作用域

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

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

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

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

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()

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

NameError: name 'c' is not defined

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

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 以上的版本函数支持类型提示功能。

def 函数名(形参:形参提示性信息) -> 返回值提示信息:...
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. 递归条件
    • 将问题继续分解的条件
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() 函数

range(start, stop[, step])

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

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

a = range(5)
print(a)
print(type(a))
print(list(a))

【2】、map() 函数

map(function, iterable, *iterables)

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

a = map(lambda x: x**2, range(1,6))
print(a)
print(type(a))for item in a:print(item)
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() 函数

filter(function, iterable)

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

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

十一、函数对象

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

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

十二、高阶函数

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

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

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 表达式专门用于创建一些简单的函数,它是函数创建的又一种方式。它的语法格式如下:

lambda 参数列表 : 返回值

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

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

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

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.rhkb.cn/news/481568.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Matlab热力图巅峰之作

准备‘data.xlsx’ 的热力图文件: main: clc; clear; close all; % 相关性气泡热图%% 数据准备 % 读取Excel文件数据 data readmatrix(data.xlsx); % 读取Excel文件中的数据%% 颜色定义 map colormap("cool"); map map([2:6,9:13],1:3)…

时序论文28|CycleNet:通过对周期模式进行建模增强时间序列预测

论文标题:CycleNet: Enhancing Time Series Forecasting through Modeling Periodic Patterns 论文链接:https://arxiv.org/abs/2409.18479v1 代码链接:https://github.com/ACAT-SCUT/CycleNet 前言 这是今年NIPS的一篇时序论文&#xff…

自动化运维(k8s)之微服务信息自动抓取:namespaceName、deploymentName等全解析

前言:公司云原生k8s二开工程师发了一串通用性命令用来查询以下数值,我想着能不能将这命令写成一个自动化脚本。 起初设计的 版本一:开头加一条环境变量,执行脚本后,提示输入:需要查询的命名空间&#xff0c…

如何把产品3D模型放到网站上进行3D展示或3D互动?

要将产品3D模型放到网站上进行3D展示或3D互动,可以按照以下步骤进行: 一、准备3D模型 使用3D建模软件(如3ds Max、Maya、Blender、C4D等)制作好产品的3D模型。 确保3D模型的格式是网站或平台所支持的,常见的格式包括…

ESP32驱动PCM5102A播放SD卡音频

文章目录 简介模块参数功能框图引脚定义通信接口和通信数据格式通信流程引脚接线ESP32和PCM5102AESP32和SD模块 主要代码spi.hSD.hAudio.h实验效果总结 简介 PCM5102A模块是一款立体声DAC模块、音频数模转换器,内部集成了PCM5102芯片。PCM5102芯片是集成了立体声模…

【人工智能】Python常用库-TensorFlow常用方法教程

TensorFlow 是一个广泛应用的开源深度学习框架,支持多种机器学习任务,如深度学习、神经网络、强化学习等。以下是 TensorFlow 的详细教程,涵盖基础使用方法和示例代码。 1. 安装与导入 安装 TensorFlow: pip install tensorflow…

【设计模式系列】解释器模式(十七)

一、什么是解释器模式 解释器模式(Interpreter Pattern)是一种行为型设计模式,它的核心思想是分离实现与解释执行。它用于定义语言的文法规则,并解释执行语言中的表达式。这种模式通常是将每个表达式抽象成一个类,并通…

【查询目录】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…

设计模式:11、迭代器模式(游标)

目录 0、定义 1、迭代器模式的四种角色 2、迭代器模式的UML类图 3、示例代码 4、迭代器的next()方法与集合的get(int index)方法的效率对比(LinkedList为例) 0、定义 提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象…

Web开发基础学习——通过React示例学习模态对话框

Web开发基础学习系列文章目录 第一章 基础知识学习之通过React组件学习模态对话框 文章目录 Web开发基础学习系列文章目录前言一、创建新的 React 应用二、 创建模态对话框组件三、修改 App.js四、 添加样式五、启动应用六、访问应用总结 前言 模态对话框(Modal D…

Unity XR Interaction Toolkit 开发教程:抓取交互【3.0以上版本】

获取完整课程以及答疑,工程文件下载: https://www.spatialxr.tech/ Unity XR Interaction Toolkit 系统化开发教程:https://www.spatialxr.tech/course/5 视频说明链接:抓取交互课程介绍【全球最新 Unity VR 系统化入门开发教程…

科技为翼 助残向新 高德地图无障碍导航规划突破1.5亿次

今年12月03日是第33个国际残疾人日。在当下科技发展日新月异的时代,如何让残障人士共享科技红利、平等地参与社会生活,成为当前社会关注的热点。 中国有超过8500万残障人士,其中超过2400万为肢残人群,视力障碍残疾人数超过1700万…

OGRE 3D----4. OGRE和QML共享opengl上下文

在现代图形应用开发中,OGRE(Object-Oriented Graphics Rendering Engine)和QML(Qt Modeling Language)都是非常流行的工具。OGRE提供了强大的3D渲染能力,而QML则用于构建灵活的用户界面。在某些应用场景中,我们需要在同一个应用程序中同时使用OGRE和QML,并且共享OpenGL…

YOLOv9改进,YOLOv9引入TransNeXt中的ConvolutionalGLU模块,CVPR2024,二次创新RepNCSPELAN4结构

摘要 由于残差连接中的深度退化效应,许多依赖堆叠层进行信息交换的高效视觉Transformer模型往往无法形成足够的信息混合,导致视觉感知不自然。为了解决这个问题,作者提出了一种聚合注意力(Aggregated Attention),这是一种基于仿生设计的token混合器,模拟了生物的中央凹…

坐标系变换

1 Clark变换 三相对称电压表达式为: 将三相电压用相量的形式表达出来,并用欧拉公式(eix(cosxisinx))写成三角函数的形式: 同时,三相电压矢量空间合成向量可表示为: 三相电压合成矢量幅值为相电…

Java 上机实践10(常用实用类)

(大家好,今天分享的是Java的相关知识,大家可以在评论区进行互动答疑哦~加油!💕) 目录 Plug:程序实现方法一(记事本) 方法二(IDEA) 实验一&…

【JavaEE初阶 — 网络编程】Socket 套接字 & UDP数据报套接字编程

1. Socket套接字 1.1 概念 Socket 套接字,是由系统提供用于网络通信的技术,是基于TCP / IP协议的网络通信的基本操作单元。基于 Socket 套接字的网络程序开发就是网络编程。 1.2 分类 Socket套接字主要针对传输层协议划分为如下三类&#x…

MacOS 如何连接 Linux NFS 服务器

以 Ubuntu 为例。 Ubuntu 服务器端设置 1. 进入 root 权限,安装 NFS 服务: apt-get update apt-get install nfs-kernel-server2. 创建共享目录: mkdir /data chown nobody:nogroup /data chmod 777 /data3. 配置 /etc/exports 文件: vi …

23种设计模式-原型(Prototype)设计模式

文章目录 一.什么是原型设计模式?二.原型模式的特点三.原型模式的结构四.原型模式的优缺点五.原型模式的 C 实现六.原型模式的 Java 实现七. 代码解析八.总结 类图: 原型设计模式类图 一.什么是原型设计模式? 原型模式(Prototype…

Docker Buildx 与 CNB 多平台构建实践

一、Docker Buildx 功能介绍 docker buildx 是 Docker 提供的一个增强版构建工具,支持更强大的构建功能,特别是在构建多平台镜像和高效处理复杂 Docker 镜像方面。 1.1 主要功能 多平台构建支持 使用 docker buildx,可以在单台设备上构建…