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

在这里插入图片描述

前言

在本篇文章中,笔者将带你深入探讨 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~~🐱‍🏍🐱‍🏍

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式Linux应用开发笔记:串口

文章目录 目的基础说明开发准备设备树应用程序 应用程序与演示代码演示 总结设备树文件 目的 串口&#xff08;UART&#xff09;是嵌入式设备中比较常用的功能。这篇文章将记录下应用程序中串口操作相关内容。 这篇文章中内容均在下面的开发板上进行测试&#xff1a; 《新唐N…

中介者模式(二十一)

相信自己&#xff0c;请一定要相信自己 上一章简单介绍了观察者模式(二十), 如果没有看过, 请观看上一章 一. 中介者模式 引用 菜鸟教程里面中介者模式介绍: https://www.runoob.com/design-pattern/mediator-pattern.html 中介者模式&#xff08;Mediator Pattern&#xff…

Django-带参数的路由编写(一)【不用正则表达式匹配的简单带参数路由】

在某urls.py文件有如下的路由配置语句&#xff1a; urlpatterns [path(app2/show/<int:id>/,views.show_id), ]语句&#xff1a; path(app2/show/<int:id>/,views.show_id),中的<int:id>就是带参数的URL中的参数部分&#xff0c;其语法格式如下&#xff1a…

Vue中如何进行图片识别与物体检测

Vue中如何进行图片识别与物体检测 随着人工智能技术的发展&#xff0c;图像识别和物体检测已经成为了很多应用场景的必备功能。在Vue中如何使用百度AI或腾讯AI等云服务实现图片识别和物体检测呢&#xff1f;本文将为您介绍一些基本概念和示例代码&#xff0c;帮助您快速入门。…

【数据库】Mysql索引、事务与存储引擎

文章目录 一、索引介绍1. 索引的概念2. 索引的作用与副作用2.1 索引的作用2.2 索引的副作用2.3 如何实现索引 3. 创建索引的原则依据4. 索引的分类和创建4.1 普通索引直接创建索引修改表方式创建创建表的时指定索引 4.2 唯一索引直接创建唯一索引修改表方式创建创建表的时候指定…

两个HC-05蓝牙之间的配对

两个HC-05蓝牙之间的配对 文章目录 两个HC-05蓝牙之间的配对1.进入AT指令模式后&#xff0c;先确定是否为AT模式&#xff1a;2.获取模块A,B的地址3.将蓝牙A配置为主模式&#xff0c;将蓝牙B配置为从模式&#xff1a;4.设置模块通信波特率,蓝牙模块A和B的配置需要相同6.验证 买了…

间接采购管理中常见的五大挑战

间接采购&#xff0c;有时也被称为间接费用或尾部支出&#xff0c;这些商品或服务不是制造产品直接必需的&#xff0c;而是日常运营所需的。 ● 办公室和行政用品 ● 商店地点的消耗品&#xff08;例如&#xff0c;清洁用品&#xff09; ● 设施管理费用 ● 专业服务 ● 旅行…

flutter创建、安装扩展包、打包apk

1、创建APK项目 要在VSCode中创建一个Flutter应用程序&#xff0c;请按照以下步骤进行操作&#xff1a; 安装Flutter SDK&#xff1a;请确保你已经安装了Flutter SDK&#xff0c;并配置了Flutter的环境。你可以在Flutter的官方网站上找到安装和设置Flutter的详细说明。 安装V…

将深度学习与传统计算机视觉进行比较

原创 | 文 BFT机器人 深度学习 (DL) 在数字图像处理中用于解决难题&#xff08;例如&#xff0c;图像着色、分类、分割和检测&#xff09;。卷积神经网络 (CNN) 等深度学习方法通过使用大数据和丰富的计算资源提高预测性能&#xff0c;突破了可能性的界限。 深度学习是机器学习…

Fiddler中 AutoResponder 使用

Fiddler的 AutoResponder &#xff0c;即URL重定向功能非常强大。不管我们做URL重定向&#xff0c;还是做mock测试等&#xff0c;都可以通过该功能进行实践。 下面&#xff0c;小酋就来具体讲下该功能的用法。 如果你想学习Fiddler抓包工具&#xff0c;我这边给你推荐一套视频…

SublimeText汉化

第一步&#xff1a;快捷键CTRLshiftp&#xff0c;弹出查找栏—找到install Package&#xff0c;并点击选择。 在这里插入图片描述 第二步&#xff1a;再次弹出的框中&#xff0c;选择ChineseLocalizations或者Chinese&#xff0c;等待安装完毕即可&#xff08;页面窗口会有提示…

Python学习48:简易英汉字典

类型&#xff1a;字典‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬ 描述‪‬‪‬…

【Mybatis】

1、Mybatis标签中resultType和resultMap的区别 在查询进行映射的时候&#xff0c;返回类型可以用resultType&#xff0c;也可以用resultMap&#xff0c;但是resultMap的功能更强大&#xff01; 1. resultType是直接表示返回类型的(对应着我们的model对象中的实体); 武断一点来…

【夜深人静学数据结构与算法 | 第二篇】后缀(逆波兰)表达式

目录 前言&#xff1a; 中缀表达式&#xff1a; 后缀表达式&#xff1a; 中缀表达式转后缀表达式&#xff1a; 后缀表达式计算结果&#xff1a; 总结&#xff1a; 前言&#xff1a; 计算机在计算四则运算的时候&#xff0c;由于括号以及运算优先级的存在&#xff0c;并不…

外卖订单管理系统(Javaweb+Mysql)

程序源码 可以通过上方代码包.rar文件下载&#xff0c;也可以在下方链接下载 链接: https://pan.baidu.com/s/1OruBEcEK70DtUbvA8UIE-w?pwddkdg &#xff08;数据库sql文件在项目根目录下data -> sql&#xff09; 设计报告 【金山文档】 外卖订单管理系统设计报告 http…

又双叒反转?美国院士复现室温超导!

室温超导又双叒反转&#xff1f; 没错&#xff0c;就是今年3月差点掀翻物理界的“21℃室温超导新材料”成果&#xff0c;来自美国罗彻斯特大学Ranga Dias团队。 尽管存在置疑&#xff0c;目前原论文仍然在《自然》期刊上可以查阅、并没有撤稿。 当时国内外很多团队都立刻尝试复…

【C++】STL的string容器介绍

目录 1、string容器 1.1声明一个c字符串 1.2string和c字符数组的比较 1.3string类操作函数介绍 1.3.1赋值操作 1.3.2字符串拼接 1.3.3字符串查找 1.3.4字符串替换 1.3.5字符串比较 1.3.6字符存取 1.3.7字符串插入 1.3.8字符串删除 1.3.9子串获取 1、string容器 在…

5、alibaba微服务nacos的引入和使用

1、项目中引入nacos 父项目中已经引入了spring-cloud-alibaba&#xff0c;这个里面就已经包含nacos依赖了&#xff0c;所以在子项目中引入nacos依赖不用添加版本信息 <dependencies><dependency><groupId>org.springframework.boot</groupId><arti…

商家中心之java商城 开源java电子商务Spring Cloud+Spring Boot+mybatis+MQ+VR全景+b2b2c

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

终极攻略!如何彻底防止Selenium被检测!

在使用Selenium进行爬虫时&#xff0c;许多朋友都会遇到各种反爬措施。 实际上&#xff0c;在绝大多数情况下&#xff0c;网站轻而易举地能够检测出你正在使用WebDriver而非标准浏览器。 本文将详细介绍如何有效防止检测的方法。 在一篇公众号文章《别去送死了。Selenium 与…