zoukankan      html  css  js  c++  java
  • [Python学习笔记-004] 可变参数*args和**kwargs

    在Python中,可变参数的传递使用*args**kwargs来实现,其中:

    • *args表示任意个位置参数(positional argument),被表示为一个只读的数组(tuple);
    • **kwargs表示任意个关键字参数(keyword argument),被表示为一个字典(dict)。

    例如:

    >>> def foo(*args, **kwargs):
    ...     print("*args:		", args)
    ...     print("**kwargs:	", kwargs)
    ...
    >>>
    >>> foo()
    *args:           ()
    **kwargs:        {}
    >>> foo(1)
    *args:           (1,)
    **kwargs:        {}
    >>> foo(1, 2)
    *args:           (1, 2)
    **kwargs:        {}
    >>>
    >>> foo(a=1, b=2)
    *args:           ()
    **kwargs:        {'a': 1, 'b': 2}
    >>>
    >>> foo(1, 2, a=1, b=2, c=3)
    *args:           (1, 2)
    **kwargs:        {'a': 1, 'b': 2, 'c': 3}
    >>>
    >>> foo(1, 2, [3, 4, 5], a=1, b=2, c={'A':1, 'B':2, 'C':3})
    *args:           (1, 2, [3, 4, 5])
    **kwargs:        {'a': 1, 'b': 2, 'c': {'A': 1, 'B': 2, 'C': 3}}
    >>>
    >>> foo(1, a=1, 2, b=2, 3, c=3)
      File "<stdin>", line 1
    SyntaxError: positional argument follows keyword argument
    >>>

    注意: 位置参数(*args)必须在关键字参数(**kwargs)的前面。

    另外,*args和**kwargs都是可以无限次地向下传递的(这一点类似Bash里的"$@"),例如:

    • foo_args.py
     1 #!/usr/bin/python
     2 
     3 from __future__ import print_function
     4 import sys
     5 
     6 def l2_foo(*args):
     7     print(">>L2:		*args =", args, "
    ")
     8 
     9 def l1_foo(head, *args):
    10     print(" >L1: head =", head, "	*args =", args)
    11     l2_foo(*args)
    12 
    13 def main(argc, argv):
    14     l1_foo(1)
    15     l1_foo(1, 2)
    16     l1_foo(1, 2, 3)
    17 
    18     return 0
    19 
    20 if __name__ == '__main__':
    21     argv = sys.argv
    22     argc = len(argv)
    23     sys.exit(main(argc, argv))

    注意L6, L9 和 L11:

     6  def l2_foo(*args):
    ..
     9  def l1_foo(head, *args):
    ..
    11      l2_foo(*args)
    • 运行foo_args.py
    $ ./foo_args.py 
     >L1: head = 1  *args = ()
    >>L2:           *args = () 
    
     >L1: head = 1  *args = (2,)
    >>L2:           *args = (2,) 
    
     >L1: head = 1  *args = (2, 3)
    >>L2:           *args = (2, 3) 

    最后,给出一个使用*args的更有工程意义的例子:

    • foo.py
     1 #!/usr/bin/python
     2 from __future__ import print_function
     3 import sys
     4 
     5 class Foo(object):
     6     def __init__(self, name, oid):
     7         self.name = name
     8         self.oid = oid
     9 
    10     def get_name(self):
    11         return self.name
    12 
    13     def set_name(self, name):
    14         self.name = name
    15 
    16     def get_info(self):
    17         return "name = %s, oid = %d" % (self.name, self.oid)
    18 
    19     def set_info(self, name, oid):
    20         self.name = name
    21         self.oid = oid
    22 
    23 class Bar(object):
    24     def __init__(self, name, oid):
    25         self.foo = Foo(name, oid)
    26 
    27     def __op_foo(self, method, *args):
    28         func = getattr(self.foo, method)
    29         try:
    30             prop = func(*args)
    31             return prop
    32         except Exception as e:
    33             print(e)
    34 
    35     def foo_set_name(self, name):
    36         return self.__op_foo('set_name', name)
    37 
    38     def foo_get_name(self):
    39         return self.__op_foo('get_name')
    40 
    41     def foo_set_info(self, name, oid):
    42         return self.__op_foo('set_info', name, oid)
    43 
    44     def foo_get_info(self):
    45         return self.__op_foo('get_info')
    46 
    47     def get_oid(self):
    48         return self.foo.oid  # XXX: Ugly but simple for demo
    49 
    50 def foo_arg0():
    51     b = Bar('Jack', 12345)
    52     s = b.foo_get_name()
    53     print("foo_arg0: name = %s, oid = %d" % (s, b.get_oid()))
    54 
    55 def foo_arg1():
    56     b = Bar('Jack', 12345)
    57     o = b.foo_set_name('Lynn')
    58     print("foo_arg1: return", o)
    59     s = b.foo_get_name()
    60     print("foo_arg1: name = %s, oid = %d" % (s, b.get_oid()))
    61 
    62 def foo_arg2():
    63     b = Bar('Jack', 12345)
    64     o = b.foo_set_info('Mary', 54321)
    65     print("foo_arg2: return", o)
    66     s = b.foo_get_info()
    67     print("foo_arg2: %s" % s)
    68 
    69 def main(argc, argv):
    70     if argc != 2:
    71         sys.stderr.write("Usage: %s <func ID>
    " % argv[0])
    72         return 1
    73 
    74     func_id = int(argv[1])
    75     exec('foo_arg%d()' % func_id)
    76 
    77     return 0
    78 
    79 if __name__ == '__main__':
    80     argv = sys.argv
    81     argc = len(argv)
    82     sys.exit(main(argc, argv))
    • 运行foo.py
    $ ./foo.py 0
    foo_arg0: name = Jack, oid = 12345
    $ ./foo.py 1
    foo_arg1: return None
    foo_arg1: name = Lynn, oid = 12345
    $ ./foo.py 2
    foo_arg2: return None
    foo_arg2: name = Mary, oid = 54321

    小结:在函数的参数列表中,零个*表示普通的位置参数, 一个*表示元组(tuple), 两个*表示字典(dict)。

    1 '*' * 0:   arg : regular arg
    2 '*' * 1:  *args: tuple (i.e. readonly list)
    3 '*' * 2: **args: dict
  • 相关阅读:
    Matlab中将数据保存为txt或dat格式四种方案
    jeecg项目能启动显示登录页面,但是登录失败,报如下错误
    回转体CAD模型的厚度测量
    安装 PostgreSQL 时出错:Warning:Problem running post-install step
    TensorFlow 张量变换
    RNNCell、LSTMCell、tf.nn.static_rnn、tf.nn.static_bidirectional_rnn和tf.nn.bidirectional_dynamic_rnn
    layers.MaxPooling1D
    tf.squeeze
    tf.layers.Conv1D,1维卷积层
    tf.keras.layers.TimeDistributed,将一个layer应用到sample的每个时序步
  • 原文地址:https://www.cnblogs.com/idorax/p/9486756.html
Copyright © 2011-2022 走看看