python中的*和**,能够让函数支持任意数量的参数,它们在函数定义和调用中,有着不同的目的

一. 打包参数

* 的作用:在函数定义中,收集所有的位置参数到一个新的元组,并将这个元组赋值给变量args

>>> def f(*args):
    print(args)

>>> f()
()
>>> f(1)
(1,)
>>> f(1, 2, 3, 4)
(1, 2, 3, 4)
>>> 

** 的作用:在函数定义中,收集关键字参数传递给一个字典,并将这个字典赋值给变量kwargs

>>> def f(**kwargs):
    print(kwargs)

>>> f()
{}
>>> f(a=1, b=2)
{'a': 1, 'b': 2}
>>> 

二. 解包参数

* 的作用:在函数调用中,* 能够将元组或者列表解包成不同的参数

>>> def func(a, b, c, d):
    print(a, b, c, d)

>>> args = (1, 2, 3, 4)
>>> func(*args)
1 2 3 4

>>> args = [1, 2, 3, 4]
>>> func(*args)
1 2 3 4

** 的作用:在函数调用中,**会以键/值的形式解包一个字典,使其成为独立的关键字参数

>>> def func(a, b, c, d):
    print(a, b, c, d)

>>> kwargs = {"a": 1, "b": 2, "c": 3, "d": 4}
>>> func(**kwargs)
1 2 3 4

三. 注意

1. 在函数定义时,* 表示打包,在函数体内部, * 仍然表示解包(print(*args)实际上也算是调用了print函数)

>>> def foo(*args, **kwargs):
    print(args)       #未解包参数
    print(*args)      #解包参数

>>> v = (1, 2, 4)
>>> d = {'a':1, 'b':12}
>>> foo(v, d)
((1, 2, 4), {'a': 1, 'b': 12})
(1, 2, 4) {'a': 1, 'b': 12}

2. 打包和解包并不能脱离函数而存在

表面上看并没有什么函数,实际上是有的,用的就是format的函数调用

>>> c = {"name": 'zhang', "age": 2}
>>> **c
SyntaxError: invalid syntax
>>>
>>> "Name:{name}, Age:{age}".format(**c)
'Name:zhang, Age:2'

参考源码中对format函数的定义

但是这个字典解包不能用print函数输出

>>> print(**c)
Traceback (most recent call last):
  File "<pyshell#40>", line 1, in <module>
    print(**c)
TypeError: 'age' is an invalid keyword argument for this function
>>> 

因为上述字典解出来的形式是这样的:

**c = name='zhang',age=2

而print函数只支持*args,不支持**kwargs

3. 在ddt中的应用

@ddt.data(*all_caseDatas)中,data是一个函数,调用函数的时候,参数*all_caseDatas自动将参数列表[{}, {}, {}...]解包为{},{},{}...,在def data(*values)函数中,*会自动将各个位置参数打包成新的元组({}, {}, {}...),然后@ddt.data就可以获取每一条数据作为测试用例了

@ddt.data(*all_caseDatas)
    def test_my_request(self, case_data):
        global global_var
        if len(global_var) != 0 and case_data["request_data"] is not None:
            for key, value in global_var.items():
                if case_data["request_data"].find(key) != -1:
                    case_data["request_data"] = case_data["request_data"].replace(key, value)

四. 练习

请写出下列代码的运行结果

def f(str1, *args, **kwargs):
    print(str1, args, kwargs)

l = [1, 2, 3]
t = [4, 5, 6]
d = {"a":7, "b":8, "c":9}

f(1, 2)
f(1, 2, 3, "python")
f("python", a=1, b=2, c=3)

print("================")

f("python", l, d)
f("python", *t)
f("python", *l, **d)
f("python", q="winning", **d)

运行结果:
1 (2,) {}
1 (2, 3, 'python') {}
python () {'a': 1, 'b': 2, 'c': 3}
================
python ([1, 2, 3], {'a': 7, 'b': 8, 'c': 9}) {}
python (4, 5, 6) {}
python (1, 2, 3) {'a': 7, 'b': 8, 'c': 9}
python () {'a': 7, 'b': 8, 'q': 'winning', 'c': 9}

需要注意的是f("python", *t)是把列表t先解包成 4, 5, 6,然后在def f(str1, *args, **kwargs):中将4, 5, 6重新打包成新的元组(4, 5, 6)再传递给变量args

python中*和**的打包和解包的更多相关文章

  1. Python 中星号作用:解包&打散

    python中’*’和’**’的使用分两个方面,一个是计算,另一个是参数传递过程中元素的打包和解包.  计算方面 ‘*’和’**’在python中最常见的作用分别是‘相乘’和‘乘幂’,如下: > ...

  2. Python 中的POST/GET包构建以及随机字符串的生成-乾颐堂

    现在,我们来用Python,创建GET包和POST包. 至于有什么用处,大家慢慢体会. Python 中包含了大量的库,作为一门新兴的语言,Python 对HTTP有足够强大的支持. 现在,我们引入新 ...

  3. [android]system.img文件的打包和解包

    1:system.img的两种格式 system2_0.img: Linux rev 1.0 ext4 filesystem data, UUID=57f8f4bc-abf4-655f-bf67-94 ...

  4. python中的模块,以及包的导入的总结

    模块导入的方式: 模块的概念:一个.py文件就称为一个模块 导入模块中函数的方式: 方式一:import  模块名 使用时:模块名.函数名() 方式二 :from 模块名 import  函数名 使用 ...

  5. 关于Python中包裹传参和解包裹的理解

    1.包裹传参 首先思考一个问题:为什么要有包裹传参?原因包括但不仅限于以下两点:①不确定参数的个数.②希望函数定义的更加松散灵活 包裹传参分两种:包裹位置传参和包裹关键字传参.先看包裹位置传参: 在这 ...

  6. pak文件的打包和解包

    pak格式的文件 一般游戏有资源 游戏素材会打包放进去 比如游戏语音 游戏多加点语音  多加一些贴图资源 外部文件实现的 素材--->pak文件--->用的时候从文件中取出来 文件的打包 ...

  7. python中收集函数的解包问题

    收集参数的解包问题 - 把参数放入list或者字典中,直接把list/dict中的值放入收集参数中- 语法:参照案例 # 收集参数的问题 def stu(*args): print("=&q ...

  8. python中pygame游戏打包为exe文件

    pyinstaller打包游戏的方法: 1.在命令窗口安装pyinstaller ->pip install pyinstaller 2.查看安装的版本信息 pyinstaller -v 3.进 ...

  9. unity学习 5.x依赖打包和解包

    unity5已经封装好了接口,所以依赖打包并没有那么神秘和复杂了. 打包: 1.定义好资源的assetBundleName 2.BuildPipeline.BuildAssetBundles,指定资源 ...

随机推荐

  1. PHP 神奇的sprintf函数

    sprintf 1.定义 sprintf() 函数将字符串进行各种类型的格式化. 2.语法 sprintf(format,arg1,arg2,arg++) format:格式类型. arg1,arg2 ...

  2. mongoose连接数据库的两种形式

    不废话,直接 ---------------------- .如果你的应用程序只使用一个数据库, 应该使用 mongoose.connect. 如果您需要创建额外的连接,使用 mongoose.cre ...

  3. 关于oracle的sequence和trigger。

    原先mysql中每个自增字段,在oracle中就需要建立一个sequence和一个trigger. 就算同一个表中有x个自增字段,那么就需要建立x个sequence和x和trigger. 实际中,我建 ...

  4. django的cookie和session以及缓存

    cookie和session cookie和session的作用: cookie和session都记录了客户端的某种状态,用来跟踪用户访问网站的整个回话.两者最大的区别是cookie的信息是存放在浏览 ...

  5. String StringBuffer StringBuilder 老生常谈

    1.String 与 StringBuffer . StringBuilder的区别 String 字符串常量 而 (StringBuffer 和 StringBuilder 字符串变量) 执行速度上 ...

  6. 10款最佳SQL Server服务器监控工具

    转自:http://server.51cto.com/sSecurity-587355.htm 推荐 | 10款最佳SQL Server服务器监控工具 服务器是网络中最重要的资源之一,SQL Serv ...

  7. ubuntu下安装qwt

    转载自:http://blog.chinaunix.net/uid-20717410-id-256767.html 相对于官方说明,特别适应于使用qt IDE开发者. //以下为引用: 虽然官网上说只 ...

  8. oradebug工具使用(转载)

    在之前的HangAnalyze 中有使用oradebug命令,在这篇文章里,我们主要是重点看一下这个oradebug命令: Oracle HANGANALYZE 功能诊断 DB hanging htt ...

  9. Django总结及Form组件

    一.model常用操作 1.13个API查询:all,filter,get ,values,values_list,distinct,order_by ,reverse , exclude(排除),c ...

  10. ASP.NET MVC Bootstrap模板选中菜单高亮显示当前项方法

    当我们处理后台显示当前页面,当前页菜单项高亮,我们可以使用js方法,也可用程序实现,使用Bootstrap模板处理高亮并展开方法之一 1.在项目中导入 <script src="/as ...