zoukankan      html  css  js  c++  java
  • python中*和**的打包和解包

    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

  • 相关阅读:
    HDU 1002 A + B Problem II
    leetcode 42.接雨水
    无向图 及其术语
    C++优先队列详解
    C++优先队列详解
    最短路
    最短路
    CF DP练习题
    CF DP练习题
    干货
  • 原文地址:https://www.cnblogs.com/my_captain/p/9410658.html
Copyright © 2011-2022 走看看