深入剖析 Python 函数参数传递机制及高级应用

news2024/12/24 10:24:24

在这里插入图片描述

前言

在本篇文章中,笔者将带你深入探讨 Python 函数传参的进阶主题。
通过阅读本篇文章,你可以深入了解 Python 函数传参的进阶主题,掌握更多高级的函数技巧,提升你的 Python 编程能力。

前面分享了Python 函数传参基础篇:《提升Python函数调用灵活性:参数传递类型详解

结合食用,效果更佳。

实现⚡⚡

参数的作用域

注意事项:

  • 使用global关键字。将函数内部的 变量 声明为全局变量,使得在函数内部修改的值也能影响到函数外部。

在这个例子中,x 在函数 func 内部是一个局部变量,它的作用范围仅限于函数内部。

而在函数外部定义的 x 是一个全局变量,可以在函数内部和外部访问。

def func():
    x = 10  # 局部变量
    print("Inside func:", x)


x = 5  # 全局变量
func()
print("Outside func:", x)

输出:

Inside func: 10
Outside func: 5

如果需要改变函数外部的值,通过使用 global 关键字,将函数内部的 x 声明为全局变量,使得在函数内部修改的值也能影响到函数外部。

def func():
    global x
    x = 10  # 局部变量
    print("Inside func:", x)


x = 5  # 全局变量
func()
print("Outside func:", x)

输出:

Inside func: 10
Outside func: 10

参数的传递方式

注意事项:

  • 避免在函数内部修改可变对象:在函数内部修改可变对象这是不建议的。
  • 如果不希望函数内部的操作影响到外部变量,可以在函数内部创建一个新的可变对象,并对其进行操作,而不是直接修改传入的可变对象。
  • 需要注意函数参数传递时对象的可变性,了解不可变对象和可变对象在函数内外的表现,并根据需要采取适当的操作来避免意外修改。

理解传值传递传引用传递的区别:

  • 传值传递是将对象的副本传递给函数,函数对副本的修改不会影响到原始对象;
  • 传引用传递是将对象的引用传递给函数,函数对引用所指向的对象的修改会影响到原始对象。

这是理解参数传递方式的关键,可以帮助我们正确处理函数内外的变量关系。




在这个例子中,a 是一个不可变对象(整数),而 b 是一个可变对象(列表)。

当将它们作为参数传递给函数时,

  • 不可变对象(如整数、字符串、元组) 是通过传值传递的,所以在函数内部对 a 的修改不会影响外部变量 x

  • 可变对象(如列表、字典) 是通过传引用传递的,所以在函数内部对 b 的修改会影响外部变量 y

def modify_value(a, b):
    a = 10
    b.append(4)


x = 5
y = [1, 2, 3]
modify_value(x, y)
print(x)  # 输出: 5
print(y)  # 输出: [1, 2, 3, 4]

匿名函数和 Lambda 表达式

注意事项:

  • lambda 关键字用于定义匿名函数:lambda 关键字用于创建一个匿名函数,也称为 lambda 表达式。它可以在需要一个简单的函数定义的地方使用,并且通常用于一次性的、简单的函数需求。
  • lambda 表达式强调了函数定义的简洁性和方便性。它适用于一些简单的函数需求,可以避免编写完整的函数定义和命名的过程,使代码更加简洁和易读。
  • 匿名函数常见于函数式编程操作,如排序、过滤和映射等。它们可以作为参数传递给其他函数,使代码更加灵活和可扩展。
  • 尽管 lambda 表达式可以提供一种简洁的函数定义方式,但请注意适用场景。对于复杂的逻辑和需要复用的函数,建议使用普通函数进行定义,以提高代码的可读性和维护性。

Python lambda用法:

lambda arguments: expression

示例 1:对数字进行相加

在这个例子中,lambda 关键字用于定义一个匿名函数,它接受两个参数 xy,并返回它们的乘积。

使用 lambda 表达式可以简洁地定义简单的函数。

add_numbers = lambda x, y: x + y
result = add_numbers(5, 3)
print("Result:", result)	# 输出: 8

示例 2:对列表进行升序排序

在这个示例中,sorted() 函数使用了 key 参数,该参数接受一个函数作为排序的依据。

通过 lambda 表达式 lambda x: x,我们指定以列表中的每个元素作为排序依据。因此,列表会按照元素的大小进行升序排序。

numbers = [5, 2, 8, 1, 9]
sorted_numbers = sorted(numbers, key=lambda x: x)
print(sorted_numbers)  # 输出: [1, 2, 5, 8, 9]

示例 3:对字典列表按照字典键进行排序

在这个示例中,有一个字典列表 persons,其中每个字典包含一个名字和年龄。

使用 sorted() 函数和 key 参数,将 lambda 表达式 lambda x: x["name"] 作为排序依据。这样,字典列表将按照字典的 "name" 键进行升序排序。

persons = [
    {"name": "Alice", "age": 25},
    {"name": "Bob", "age": 30},
    {"name": "Charlie", "age": 20}
]

sorted_persons = sorted(persons, key=lambda x: x["name"])
print(sorted_persons)
# 输出: [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}, {'name': 'Charlie', 'age': 20}]

装饰器

装饰器可以实现很多有趣的功能,这里只对基础使用做一下介绍。

注意事项:

  • 确保装饰器函数的返回值是一个函数:装饰器函数必须返回一个函数对象,以便能够正确地替代原始函数。
  • 装饰器的作用是修改函数的行为:装饰器的目的是在不修改原始函数源代码的情况下,添加一些额外的功能或修改函数的行为。
  • 可以链式应用多个装饰器:Python 允许链式应用多个装饰器,即在函数定义前使用多个装饰器语句。装饰器的应用顺序与装饰器语句的顺序相反,最后应用的装饰器最先执行。
  • 装饰器的顺序是从上到下的。

示例一:将字母转换为大写装饰器

在这个例子中,uppercase_decorator 是一个装饰器函数,它接受一个函数作为参数,并返回一个新的函数。

这个装饰器函数将原始函数的返回值转换为大写形式。通过在函数定义前使用 @ 符号应用装饰器,可以直接将装饰器应用于函数。

def uppercase_decorator(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result.upper()

    return wrapper


@uppercase_decorator
def demo(name):
    return "Hello, " + name


result = demo("Frica")
print(result)  # 输出: HELLO, Frica

示例二:将字母转换为大写装饰器并添加<b>标签

在示例中,demo 函数先应用 uppercase_decorator,然后应用 bold_decorator

最终的执行顺序是先执行 bold_decorator 的包装函数,然后执行 uppercase_decorator 的包装函数。最后,调用 demo("Frica") 会返回 <b>HELLO, FRICA</b>

def uppercase_decorator(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result.upper()

    return wrapper


def bold_decorator(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return "<b>" + result + "</b>"

    return wrapper


@bold_decorator
@uppercase_decorator
def demo(name):
    return "Hello, " + name


result = demo("Frica")
print(result)  # 输出: <b>HELLO, FRICA</b>

参数的打包和解包

注意事项:

  • 打包:通过使用 *** 运算符,可以将传递给函数的参数打包成一个元组或字典;
  • 解包:通过使用 *** 运算符,可以将元组或字典中的值解构为单独的参数,并将它们传递给函数;
  • 在函数调用时,使用 * 运算符将元组中的元素分别传递给函数的位置参数;
  • 在函数调用时,使用**运算符将字典的键值对打包并传递给函数的关键字参数;
  • 通过参数解包,可以轻松地将可迭代对象的元素传递给函数,而无需一个个地指定参数的值。这种方式提供了更灵活和方便的函数调用方式,并使代码更加简洁易读。

在这个例子中,datainfo 是元组和字典,通过解构操作符 *** 将它们的值解构为单独的参数。

paramsdetails 是普通的参数值,通过打包操作符 *** 将它们的值打包成元组或字典作为参数传递给函数。

def demo(name, age):
    print(f"Name: {name},", f"Age: {age}")


# 参数解包
data = ("Frica", 25)
demo(*data)  # 输出: Name: Frica, Age: 25

# 参数解包
info = {"name": "dd", "age": 30}
demo(**info)  # 输出: Name: dd, Age: 30

参数类型注解

这个在上一篇文章中有介绍,无论何时,为你的函数和参数添加类型注解,这是很有必要的。

作用如下:

  • 提供类型提示:类型注解可以指定函数参数和返回值的预期类型,从而提供给开发者更明确的类型提示。这有助于开发者理解函数的输入和输出,并在代码编写过程中提供自动补全和错误检查的功能。
  • 增加代码可读性:类型注解可以提高代码的可读性,使代码更加清晰易懂。通过类型注解,开发者可以清楚地了解函数参数的期望类型,从而更好地理解函数的作用和用法。
  • 增强代码健壮性:类型注解可以在编译时或运行时进行类型检查,从而捕获潜在的类型错误。通过类型检查,可以避免在函数调用时传递错误类型的参数,提前发现并修复类型相关的问题,提高代码的健壮性和可靠性。
  • 提升代码维护性:类型注解可以帮助开发团队更好地理解代码,并减少对代码的误解。在代码维护和重构过程中,类型注解可以作为重要的参考信息,帮助开发者正确修改和调整函数的使用方式。
  • 支持静态类型检查工具:添加类型注解可以支持使用静态类型检查工具,例如 MyPy、Pyright 等。这些工具可以对代码进行静态分析,发现类型相关的问题,并提供进一步的建议和修复方案。

需要注意的是,类型注解并不会影响代码的实际执行,它们只是提供给开发者和工具使用的信息。

在 Python 中,类型注解是可选的,并且不会导致运行时错误。但是,类型注解可以在代码开发和维护过程中提供很多有益的帮助,

def demo(name: str, age: int) -> str:
    return "Hello, " + name + "! You are " + str(age) + " years old."


print(demo("Frica", 25))	# 输出: Hello, Frica! You are 25 years old.

总结✨✨

本篇文章深入介绍了Python中函数传参机制的高级应用。

  • 参数的作用域:介绍了局部作用域、全局作用域和嵌套作用域的概念及其关系。这有助于理解在不同作用域中如何访问和操作变量。

  • 参数的传递方式:探讨了传值调用和传引用调用的区别,以及可变对象和不可变对象的概念。这对于理解函数参数的传递机制非常重要。

  • 匿名函数和 Lambda 表达式:介绍了匿名函数的定义和使用,以及 Lambda 表达式的语法和应用场景。这些技巧可以简化代码并提高可读性。

  • 装饰器:解释了装饰器的作用和用法,包括如何定义和应用装饰器来增强函数的功能。装饰器是 Python 中强大的函数修饰工具。

  • 参数的解构和打包:讨论了参数解构和打包的操作符 *** 的使用方法,以及如何处理多个参数的情况。这些技巧可以增加代码的灵活性。

  • 参数类型注解:介绍了参数类型注解的概念和用法,以及如何在函数定义时指定参数的类型。这有助于提高代码的可读性和可维护性。

总体上,这些主题涵盖了函数传参的关键概念和技巧,适合进阶的 Python 程序员学习和掌握。

后话🏹🏹

本次分享到此结束,
see you~~🐱‍🏍🐱‍🏍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/650737.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图像生成--对抗生成模型

生成模型概述 对抗生成模型 机器学习中的两大主要问题&#xff1a; 判别生成 判别模型的典型代表即为图像分类任务&#xff0c;即给定一个数据&#xff0c;判定他是哪一类。 判别模型学习到的是一个概率&#xff08;贝叶斯过程&#xff09; 而生成模型的区别在于&#xf…

【Elacticsearch】 原理/数据结构/面试经典问题整理

对Elacticsearch 原理/数据结构/面试经典问题整理的文章&#xff1b; 映射 | Elasticsearch: 权威指南 | Elastic Elacticsearch介绍 Elasticsearch,这里简称ES。ES是一个开源的高可用高扩展的分布式全文搜索与分析引擎&#xff0c;可以提供PB级近实时的数据存储和检索能力&am…

SpringBoot自定义starter入门

一、创建一个普通的Maven项目 pom.xml文件修改 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation&quo…

你知道如何将音频转文字吗?

我跟你们说&#xff0c;我认识一名盲人音乐人&#xff0c;他很热爱音乐创作&#xff0c;但是因为听力的限制&#xff0c;无法像其他人那样从录音中获取音乐素材。然而&#xff0c;有一天他听说了一个神奇的功能——音频转文字&#xff0c;这个功能可以将音频文件转换成文字文本…

从技术谈到管理,把系统优化的技术用到企业管理

很多技术人员在职业上对自己要求高&#xff0c;工作勤奋&#xff0c;承担越来越大的责任&#xff0c;最终得到信任&#xff0c;被提拔到管理岗位。但是往往缺乏专业的管理知识&#xff0c;在工作中不能从整体范围优化工作流程&#xff0c;仍然是“个人贡献者”的工作方式&#…

低功耗晶振电路设计

晶振电路设计 晶振中负性阻抗的原理 晶振的回路主要由两部分组成&#xff0c; 一部分是激活分支&#xff0c; 用于提供能量给晶振启动直至达到稳定的相位&#xff0c;另一部分是被动分支&#xff0c; 主要由电阻&#xff0c; 两个外部负载电容以及所有的寄生电容&#xff0c;…

手写RPC总结篇

协议制定&#xff1a;client到server做交互的通信协议&#xff0c;比如request response 网络端点peer 难点1 : Jetty嵌入 ◆jetty Server ◆ServletContextHandler ◆ServletHolder jetty server 起到网络监听的作用ServletContextHandler注册到jetty server中ServletHolde…

测试开发之Python自动化 Pytest 之 fixture

Pytest 之 fixture unittest 和 nose 都支持 fixture 的,但是 fixture 在 pytest 里使用更灵活。也算是 pytest 的一个闪光点吧可以理解为一个跟 setup 和 teardown 这种前后置类似的东西。但是比它们要强大、灵活很多 fixtur 当做参数传入 # -*- coding: utf-8 -*-import p…

图像处理实战02-yolov5目标检测

yolov5 YOLOv5 是一种目标检测算法&#xff0c;它是 YOLO (You Only Look Once) 系列算法的最新版本。YOLOv5 采用了一种新的架构&#xff0c;它包括一个基于 CSPNet (Cross Stage Partial Network) 的主干网络以及一系列改进的技巧&#xff0c;如多尺度训练、数据增强、网络混…

互联网行业-镭速文件传输系统方案

互联网行业是一个快速变化和高度竞争的行业&#xff0c;这一行业需要传输大量的数据、代码和文件。在互联网企业的生产和运营过程中&#xff0c;需要传输各种敏感和大型的文件&#xff0c;例如业务报告、数据分析、软件代码等。这些文件需要在不同的部门、不同的地点之间高效地…

微服务springcloud 07 hystrix + turbine 集群聚合监控

01.hystrix dashboard 一次只能监控一个服务实例&#xff0c;使用 turbine 可以汇集监控信息&#xff0c;将聚合后的信息提供给 hystrix dashboard 来集中展示和监控 02.新建 sp10-turbine 项目 03.pom.xml <?xml version"1.0" encoding"UTF-8"?&…

C语言---malloc(0)会产生什么结果,真的是空指针吗?

前言 &#xff08;1&#xff09;几天前在一个交流群中看到有人说&#xff0c;面试问malloc(0)会怎么样是真的恶心。 &#xff08;2&#xff09;这个突然激起了我的好奇心。居然还可以malloc(0)&#xff1f;&#xff01; &#xff08;3&#xff09;经过测试最后&#xff0c;发现…

基于Java学生课外知识学习网站设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

PulsarMQ系列入门篇

文章目录 介绍&#xff1a;部署安装讲解:安装单机版本测试&#xff08;Linux下&#xff09;&#xff1a; 介绍&#xff1a; PulsarMQ 现托管于apache Apache 软件基金会顶级项目&#xff0c;2016年由雅虎公司开源的分布式多租户消息中间件 &#xff0c;是下一代云原生分布式消息…

PaddleOCR #hello paddle: 从普通程序走向机器学习程序 - 初识机器学习

这篇示例向你介绍普通程序跟机器学习程序的区别&#xff0c;并带着你用百度飞桨框架&#xff0c;实现第一个机器学习程序&#xff0c;并初步认识机器学习。 作为一名开发者&#xff0c;你最熟悉的开始学习一门编程语言&#xff0c;或者一个深度学习框架的方式&#xff0c;可能是…

万字长文:大模型训练避坑指南

自 2022 年 11 月底 ChatGPT 发布以来&#xff0c;大模型的热度持续发酵&#xff0c;相信高屋建瓴的讨论大家已经看了很多了。今天我们选择从实用角度&#xff0c;分别就算力、算法、工程、数据和团队等方向讨论了训练一个千亿参数量级的大语言模型和 ChatGPT 需要些什么&#…

4.17 TCP三次握手 4.18滑动窗口 4.19TCP四次挥手

4.17 TCP三次握手 TCP 是一种面向连接的单播协议&#xff0c;在发送数据前&#xff0c;通信双方必须在彼此间建立一条连接。所谓的“连接”&#xff0c;其实是客户端和服务器的内存里保存的一份关于对方的信息&#xff0c;如 IP 地址、端口号等。 TCP 可以看成是一种字节流&a…

i.MX 91x推出,飞凌嵌入式携手NXP打造更强大、更经济、更安全的解决方案

NXP在COMPUTEX 2023上发布了i.MX 91应用处理器系列&#xff0c;作为i.MX 9系列的入门级产品&#xff0c;i.MX 91x简化了高性价比边缘设备的开发过程&#xff0c;助力构建需要安全性、高性能表现以及Linux支持的可扩展、高可靠性的平台&#xff0c;可满足下一代基于Linux的物联网…

【数据库三】MySQL索引

MySQL索引、事务与存储引擎 1.MySQL索引1.1 索引的概念1.2 索引的作用​1.3 索引的副作用​1.4 创建索引的原则依据​ 2.索引的分类和创建2.1 普通索引2.2 唯一索引2.3 主键索引2.4 组合索引2.5 全文索引 3. 查看索引4.删除索引5. 知识点总结 1.MySQL索引 1.1 索引的概念 索引…

基于html+css的图展示127

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…