python参数传递*args和**kwargs

python参数传递*args和**kwargs

*

实际上真正的Python参数传递语法是 ****args**kwargs 只是一种约定俗成的编程实践。我们也可以写成 *vars**kvars 。就如同其他常规变量的命名一样, argskwargs 只是一种习惯的名称。

*args**kwargs 一般是用在函数定义的时候。二者的意义是允许定义的函数接受任意数量的参数。也就是说我们在函数被调用前并不知道也不限制将来函数可以接收的参数数量。在这种情况下我们可以使用 *args**kwargs

接下来我们分别分析 *args**kwargs 在函数定义时(即在形参列表中)和在函数调用时的用法。

在函数定义时的*和**(即函数形参列表中的*和**)

在函数定义时的*args

*args 用来表示函数接收可变长度的非关键字参数列表作为函数的输入。我们通过一个例子来体会参数列表中的 *args 的用法:

def test_args(normal_arg, *args):print("normal arg:" + normal_arg)print(type(args))for arg in args:print("another arg through *args :" + arg)test_args("normal", "Python", "C", "C++")

输出:

normal arg:normal
<class 'tuple'>
another arg through *args :Python
another arg through *args :C
another arg through *args :C++

在函数定义时的**kwargs

**kwargs 表示函数接收可变长度的关键字参数字典作为函数的输入。当我们需要函数接收带关键字的参数作为输入的时候,应当使用 **kwargs。我们可以通过以下这个例子来进一步理解 **kwargs

def test_kwargs(**kwargs):if kwargs is not None:print(type(kwargs))for key, value in kwargs.items():print("{} = {}".format(key,value))test_kwargs(name="python", value="5")

输出:

<class 'dict'>
name = python
value = 5

如何处理关键字参数中的未知性

虽说参数列表中的 *和**使得我们可以接收任意多个参数变量,但是我们在设计函数时肯定也不是随便什么参数都去处理的,函数的调用者应该明白在 *args**kwargs 中需要传递什么参数,可以传递什么参数(比如深度学习模型中的模型结构的设置,如模型深度,dropout概率等)。并且我们在函数体中来处理这些参数。

然而,我们并不知道调用者在调用时会传什么,哪些又应该在调用时使用默认值。这里笔者参考了 timm 视觉库对 ViT 的实现。

在_create_vision_trainsformer 函数中,我们只要处理和我们相关的传入参数:

def _create_vision_transformer(variant, pretrained=False, default_cfg=None, **kwargs):default_cfg = default_cfg or default_cfgs[variant]if kwargs.get('features_only', None):raise RuntimeError('features_only not implemented for Vision Transformer models.')# NOTE this extra code to support handling of repr size for in21k pretrained modelsdefault_num_classes = default_cfg['num_classes']num_classes = kwargs.get('num_classes', default_num_classes)repr_size = kwargs.pop('representation_size', None)if repr_size is not None and num_classes != default_num_classes:# Remove representation layer if fine-tuning. This may not always be the desired action,# but I feel better than doing nothing by default for fine-tuning. Perhaps a better interface?_logger.warning("Removing representation layer for fine-tuning.")repr_size = Nonemodel = build_model_with_cfg(VisionTransformer, variant, pretrained,default_cfg=default_cfg,representation_size=repr_size,pretrained_filter_fn=checkpoint_filter_fn,pretrained_custom_load='npz' in default_cfg['url'],**kwargs)return model

可以看到,我们传入的 kwargs 是一个字典,这里使用了字典的 getpop 两种方法来处理。

python字典的get和pop方法

pop

dict.pop(key[,default])

删除字典给定键 key 及对应的值,返回值为被删除的值,若 key 不存在,则返回 default 参数所指定的默认值。

get

dict.get(key, default=None)

函数返回指定键的值,若 key 不存在,则返回 default 参数所指定的默认值。

通过这两种方法,我们就能够实现在 kwargs 中没有传入参数时使用默认值,而在有指定参数时,使用传入值。

在函数调用时的*和**

  • 列表前面加星号作用是将列表解开成两个独立的参数,传入函数,

  • 字典前面加两个星号,是将字典解开成独立的元素作为形参。

如果我们有一个加法函数 add()

def add(a, b):return a + b

函数调用时的*

我们可以这样调用它:先构造一个列表,在用 * 将列表解开,将其中的值作为参数逐个传入函数的参数列表:

data_list = [1, 2]
print(add(*data_list))
# 输出:3

就相当于

print(add(1, 2))

我们甚至可以直接打印出 * 解开列表之后的参数序列:

print(*data_list)
# 输出:1 2

函数调用时的**

我们还可用字典的形式来调用它:构造一个字典,键名为要调用函数的形参名称,值为我们要传递的参数:

data_dict = {'a': 1, 'b': 2}
print(add(**data_dict))
# 输出:3

相当于:

print(add(a=1, b=2))

注意这里我们构造的字典的键名必须对应函数形参列表中的形参名称,否则汇报错,比如

data_dict = {'a': 1, 'c': 2}
print(add(**data_dict))

相当于:

print(data(a=1, c=2))

将会报错:

TypeError: add() got an unexpected keyword argument 'c'

两种使用方式的统一理解

以关键字参数 **kwargs 为例,我们这样考虑:

我们提到过,对于一个字典 dict={'a': 1, 'b': 2} ,给它加上 ** 号 ,相当于是将其中的元素解开单拎出来,即 **dict 相当于 a=1, b=2,这正好符合我们调用函数传递参数时的写法。

而当 **kwargs 在中形参列表中时,我们传入 a=1, b=2,看一下,正好对应我们上面的 **dict (只是名字不一样,开始提到过,这无妨),那也把 ** 号去掉后,kwargs 就相当于我们上面的 dict ,是一个字典:{'a': 1, 'b': 2} ,这就说明了为什么我们上面介绍函数定义时的 **kwargs 的例子中,type(kwargs)dict,并且在函数体中我们也是通过调用字典类的方法(如 itemspopget)来处理它。

Ref:

https://www.jianshu.com/p/be92113116c8

https://github.com/rwightman/pytorch-image-models

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

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

相关文章

听GPT 讲Rust源代码--src/tools(25)

File: rust/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs 在Rust源代码中&#xff0c;suspicious_command_arg_space.rs文件位于clippy_lints工具包的methods目录下&#xff0c;用于实现Clippy lint SUSPICIOUS_COMMAND_ARG_SPACE。 Clippy是Ru…

Java一次编译,到处运行是如何实现的

Java一次编译&#xff0c;到处运行是如何实现的 转自&#xff1a;https://cloud.tencent.com/developer/article/1415194 &#xff08;排版微调&#xff09; JAVA编译运行总览 Java是一种高级语言&#xff0c;要让计算机执行你撰写的Java程序&#xff0c;也得通过编译程序的…

JIT(动态编译)和AOT(静态编译)编译技术比较

JIT&#xff08;动态编译&#xff09;和AOT&#xff08;静态编译&#xff09;编译技术比较 转自&#xff1a;https://www.cnblogs.com/tinytiny/p/3200448.html Java 应用程序的性能经常成为开发社区中的讨论热点。因为该语言的设计初衷是使用解释的方式支持应用程序的可移植…

python解释器

python解释器 计算机编程语言 本部分参考自&#xff1a;https://zhuanlan.zhihu.com/p/141212114 从计算机编程语言说起&#xff0c;它主要分为三类&#xff1a;机器语言、汇编语言、高级语言。 机器语言是一种计算机可以直接识别并执行的二进制指令集。由于其可以直接交给…

编译型语言与解释型语言

编译型语言与解释型语言 首先要说明&#xff0c;编译型语言与解释型语言这种分类方法是不科学的&#xff0c;或者说已经过时了&#xff0c;但是这种称呼大抵还是能够让人明白我们将要讨论的是什么东西。 文中所列参考是笔者认为比较有帮助的一些扩展阅读内容。 首先贴一个很形…

常见的各种shell及其区别

常见的各种shell及其区别 引子 for((i1;i<10;i)); do echo $(expr $i \* 3 1); done 网上搜到的 shell for循环脚本&#xff0c;别人都能正常运行&#xff0c;我却报错&#xff1a; Syntax error: Bad for loop variable究竟是怎么回事呢&#xff1f; shell简介…

shell脚本 变量

shell脚本 变量类型 什么是Shell变量 用一个固定的字符串去表示不固定的内容。 Shell变量的类型 shell脚本中自定义变量的类型&#xff0c;我们这里分为&#xff1a; 自定义变量环境变量位置变量与定义变量 这四类&#xff0c;它们有一些相同点&#xff0c;但又有些不同点…

攻防世界web新手区解题 /cookie / disabled_button / weak_auth

cookie 题目描述&#xff1a;X老师告诉小宁他在cookie里放了些东西&#xff0c;小宁疑惑地想&#xff1a;‘这是夹心饼干的意思吗&#xff1f;’ 使用burp suite抓包查看 发现提示&#xff1a; look-herecookie.php 于是在url后加上 cookie.php 得到提示查看返回 就得到了f…

Python 函数式编程

Python 函数式编程 转自&#xff1a;https://www.liaoxuefeng.com/wiki/1016959663602400/1017328525009056&#xff0c;推荐去该链接读原文&#xff0c;有习题和热烈的评论区交流。 函数式编程 函数是Python内建支持的一种封装&#xff0c;我们通过把大段代码拆成函数&…

Python中的生成器与迭代器

Python中的生成器与迭代器 转自&#xff1a;https://www.liaoxuefeng.com/wiki/1016959663602400/1017323698112640&#xff0c;推荐去该链接读原文&#xff0c;有习题和热烈的评论区交流。 生成器 通过列表生成式&#xff0c;我们可以直接创建一个列表。但是&#xff0c;受…

基于GET报错的sql注入,sqli-lab 1~4

根据注入类型可将sql注入分为两类&#xff1a;数字型和字符型 例如&#xff1a; 数字型&#xff1a; sleect * from table where if 用户输入id 字符型&#xff1a;select * from table where id 用户输入id &#xff08;有引号) 通过URL中修改对应的D值&#xff0c;为正常数字…

Python 装饰器详解(上)

Python 装饰器详解&#xff08;上&#xff09; 转自&#xff1a;https://blog.csdn.net/qq_27825451/article/details/84396970&#xff0c;博主仅对其中 demo 实现中不适合python3 版本的语法进行修改&#xff0c;并微调了排版&#xff0c;本转载博客全部例程博主均已亲测可行…

xss原理和注入类型

XSS漏洞原理 : XSS又叫CSS(cross Site Script), 跨站脚本攻击,指的是恶意攻击者往Web页面里插入恶意JS代码,当用户浏览该页时,嵌入其中的Web里的JS代码就会被执行,从而达到恶意的特殊目的. 比如:拿到cooike XSS漏洞分类: 反射性(非存储型) payload没有经过存储,后端接收后,直接…

Python 装饰器详解(中)

Python 装饰器详解&#xff08;中&#xff09; 转自&#xff1a;https://blog.csdn.net/qq_27825451/article/details/84581272&#xff0c;博主仅对其中 demo 实现中不适合python3 版本的语法进行修改&#xff0c;并微调了排版&#xff0c;本转载博客全部例程博主均已亲测可行…

存储型xss案例

存储型xss原理: 攻击者在页面插入xss代码,服务端将数据存入数据库,当用户访问存在xss漏洞的页面时,服务端从数据库取出数据展示到页面上,导致xss代码执行,达到攻击效果 案例: 在一个搭建的论坛网站中, 根据存储型xss注入的条件,要找到可以存储到数据库的输入位置,并且这个位置…

反射型XSS案例

**原理:**攻击者将url中插入xss代码,服务端将url中的xss代码输出到页面上,攻击者将带有xss代码的url发送给用户,用户打开后受到xss攻击 需要url中有可以修改的参数 案例: 可能存在反射型xss的功能(点) : 搜索框等&#xff08;所有url会出现参数的地方都可以尝试&#xff09;……

Python 装饰器详解(下)

Python 装饰器详解&#xff08;下&#xff09; 转自&#xff1a;https://blog.csdn.net/qq_27825451/article/details/84627016&#xff0c;博主仅对其中 demo 实现中不适合python3 版本的语法进行修改&#xff0c;并微调了排版&#xff0c;本转载博客全部例程博主均已亲测可行…

xss-lab靶场通关writeup(1~6.......在更新)

level 2 : 标签被编码&#xff0c;利用属性完成弹窗 输入 发现没有弹窗 查看源代码&#xff1a; 发现&#xff1a; <>符号被编码 说明keybord参数进行了处理&#xff0c;那么只能从属性上进行恶意编码&#xff1a;先将属性的引号和标签闭合&#xff0c;用 // 将后面的…

PyTorch 分布式训练DDP 单机多卡快速上手

PyTorch 分布式训练DDP 单机多卡快速上手 本文旨在帮助新人快速上手最有效的 PyTorch 单机多卡训练&#xff0c;对于 PyTorch 分布式训练的理论介绍、多方案对比&#xff0c;本文不做详细介绍&#xff0c;有兴趣的读者可参考&#xff1a; [分布式训练] 单机多卡的正确打开方式…

Linux free 命令详解

Linux free 命令详解 free 命令用来查看系统中已用的和可用的内存。 命令选项及输出简介 关于各种命令的功能和命令选项&#xff0c;还是推荐英语比较好的同学直接看手册 RTFM&#xff1a;man free。这里简单总结一下一些重点&#xff1a; 功能及输出简介 free 命令显示系…