Bare asterisk in function arguments?

后端 未结 6 1189
孤街浪徒
孤街浪徒 2020-11-22 06:22

What does a bare asterisk in the arguments of a function do?

When I looked at the pickle module, I see this:

pickle.dump(obj, file, protocol=None, *,         


        
相关标签:
6条回答
  • 2020-11-22 07:05

    While the original answer answers the question completely, just adding a bit of related information. The behaviour for the single asterisk derives from PEP-3102. Quoting the related section:

    The second syntactical change is to allow the argument name to
    be omitted for a varargs argument. The meaning of this is to
    allow for keyword-only arguments for functions that would not
    otherwise take a varargs argument:
    
        def compare(a, b, *, key=None):
            ...
    

    In simple english, it means that to pass the value for key, you will need to explicitly pass it as key="value".

    0 讨论(0)
  • 2020-11-22 07:05
    def func(*, a, b):
        print(a)
        print(b)
    
    func("gg") # TypeError: func() takes 0 positional arguments but 1 was given
    func(a="gg") # TypeError: func() missing 1 required keyword-only argument: 'b'
    func(a="aa", b="bb", c="cc") # TypeError: func() got an unexpected keyword argument 'c'
    func(a="aa", b="bb", "cc") # SyntaxError: positional argument follows keyword argument
    func(a="aa", b="bb") # aa, bb
    

    the above example with **kwargs

    def func(*, a, b, **kwargs):
        print(a)
        print(b)
        print(kwargs)
    
    func(a="aa",b="bb", c="cc") # aa, bb, {'c': 'cc'}
    
    0 讨论(0)
  • 2020-11-22 07:06

    Semantically, it means the arguments following it are keyword-only, so you will get an error if you try to provide an argument without specifying its name. For example:

    >>> def f(a, *, b):
    ...     return a + b
    ...
    >>> f(1, 2)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: f() takes 1 positional argument but 2 were given
    >>> f(1, b=2)
    3
    

    Pragmatically, it means you have to call the function with a keyword argument. It's usually done when it would be hard to understand the purpose of the argument without the hint given by the argument's name.

    Compare e.g. sorted(nums, reverse=True) vs. if you wrote sorted(nums, True). The latter would be much less readable, so the Python developers chose to make you to write it the former way.

    0 讨论(0)
  • 2020-11-22 07:19

    Suppose you have function:

    def sum(a,key=5):
        return a + key 
    

    You can call this function in 2 ways:

    sum(1,2) or sum(1,key=2)

    Suppose you want function sum to be called only using keyword arguments.

    You add * to the function parameter list to mark the end of positional arguments.

    So function defined as:

    def sum(a,*,key=5):
        return a + key 
    

    may be called only using sum(1,key=2)

    0 讨论(0)
  • 2020-11-22 07:21

    I've found the following link to be very helpful explaining *, *args and **kwargs:

    https://pythontips.com/2013/08/04/args-and-kwargs-in-python-explained/

    Essentially, in addition to the answers above, I've learned from the site above (credit: https://pythontips.com/author/yasoob008/) the following:

    With the demonstration function defined first below, there are two examples, one with *args and one with **kwargs

    def test_args_kwargs(arg1, arg2, arg3):
        print "arg1:", arg1
        print "arg2:", arg2
        print "arg3:", arg3
    
    # first with *args
    >>> args = ("two", 3,5)
    >>> test_args_kwargs(*args)
    arg1: two
    arg2: 3
    arg3: 5
    
    # now with **kwargs:
    >>> kwargs = {"arg3": 3, "arg2": "two","arg1":5}
    >>> test_args_kwargs(**kwargs)
    arg1: 5
    arg2: two
    arg3: 3
    

    So *args allows you to dynamically build a list of arguments that will be taken in the order in which they are fed, whereas **kwargs can enable the passing of NAMED arguments, and can be processed by NAME accordingly (irrespective of the order in which they are fed).

    The site continues, noting that the correct ordering of arguments should be:

    some_func(fargs,*args,**kwargs)
    
    0 讨论(0)
  • 2020-11-22 07:25

    Bare * is used to force the caller to use named arguments - so you cannot define a function with * as an argument when you have no following keyword arguments.

    See this answer or Python 3 documentation for more details.

    0 讨论(0)
提交回复
热议问题