Python positional args and keywords args

I am reading mercurial source codes and found such func def in .py commands:

def import_(ui, repo, patch1=None, *patches, **opts): ... 

in python, postgroup arguments must be preceded by args keywords. But here patch1 is the keyword argument followed by the positional argument *patches . why is this normal?

+8
function python func
source share
4 answers

Just browse through PEP 3102 , it also seems to have something to do with it .

To summarize, patches and options should accept variable arguments, but later you need to accept keyword arguments. Keyword arguments are passed as a dictionary, where variable positional arguments will be wrapped as tuples .

From your example

 def import_(ui, repo, patch1=None, *patches, **opts): 

Any positional parameters after u1,repo and patch1 will be wrapped as tuples in the patches. Any keyword arguments following variable positional arguments will be placed as Dictionary objects through selections.

Another important thing is that the burden is on the caller to ensure that the non-keyword arg after keyword arg condition is not violated.

So, something that violates this will result in a syntax error.

for example

Called as

  import_(1,2,3,test="test") import_(1,2,3,4,test="test") import_(1,2,3,4,5) import_(1,2,patch1=3,test="test") 

but

 import_(1,2,3,patch1=4,5) 

will result in a SyntaxError: non-keyword arg after keyword arg syntax error SyntaxError: non-keyword arg after keyword arg

In the first valid case, import_(1,2,3,test="test")

 u1 = 1, repo = 2, patch1 = 3, patches = () and opts={"test":"test"} 

In the second valid case, import_(1,2,3,patch1=4,test="test")

 u1 = 1, repo = 2, patch1 = 3 , patches = (4) and opts={"test":"test"} 

In the third valid case, import_(1,2,3,4,5)

 u1 = 1, repo = 2, patch1 = 3 , patches=(4,5), and opts={} 

In the fourth valid case, import_(1,2,patch1=3,test="test")

 u1 = 1, repo = 2, patch1 = 3 , patches=(), and opts={"test":"test"} you can use patch1 as a keywords argument but doing so you cannot wrap any variable positional arguments within patches 
+8
source share

You might be confusing the definition of a function with the syntax of a function call.

patch1 not an arg keyword, it is a positional arg with the default argument value assigned.

*patches is a list of arguments, not a positional argument.


Please see this section from the official guides:

Now let me summarize the main points using this function as an example:

 def f1(a1, a2, a3=None, *args, **kwargs): print a1, a2, a3, args, kwargs 

Function Definition

You have several arguments that are explicitly defined by name ( a1 , a2 and a3 ), of which a3 will be initialized to None by default if it is not specified during the call. Arguments a1 and a2 must be provided in any valid call to this function.

The function can be called with additional arguments that will be displayed in the kwargs dictionary (when delivered by keyword) or in the args list (if it is not specified by keyword). If args and kwargs not present in the function definition, the caller will not be allowed to add more arguments than those explicitly specified in the function definition to call the function.

In the function definition, you need to specify explicit arguments without a default initializer, and then explicit arguments with a default initializer, a third argument list, and finally a keyword argument dictionary.

Function call

There are various ways to call a function. For example, the following calls will give equal results:

 f1(1, 2) # pass a1 and a2 as positional arguments f1(a2=2, a1=1) # pass a1 and a2 as keyword arguments f1(1, a2=2) # pass a1 as positional argument, a2 as keyword argument 

That is, the arguments of the function are resolved either by their position (positional or non-keyword arguments), or by their specified name (keyword arguments).

When calling a function, you first need to put the arguments without a keyword, and finally the keyword arguments, for example

 # demonstrate how some additional positional and keyword arguments are passed f1(1, 2, 3, 4, 5, 6, 7, a4=8, a5=9, a6=10) # prints: # 1 2 3 (4, 5, 6, 7) {'a5': 9, 'a4': 8, 'a6': 10} 

Now positional arguments that do not fit into the list of specified arguments in the function definition will be added to the *args argument list and keyword arguments that do not fit into the list of specified arguments in the function definition will be inserted into the **kwargs keyword argument dictionary.

+3
source share

Since passing a key into a keyword argument may not be necessary if its position is unambiguous. Note:

 >>> def f(ui, patch1=None, *patches, **opts): ... print patch1 ... >>> f(1, 2) 2 >>> f(1, patch1='a', 3) File "<stdin>", line 1 SyntaxError: non-keyword arg after keyword arg >>> f(1, 'a', 3) a 

As you can see, omitting the patch1 key makes this argument not a keyword, therefore it does not throw a SyntaxError exception.


EDIT: moooeeeep in its answer says that

"patch1 is not an arg keyword, it is a positional arg with the default argument value assigned."

This is not so, but the IMO of the following case shows why such a definition is ambiguous:

 >>> def f(ui, p1=None, p2=None, *patches, **opts): ... print p1, p2 ... >>> f(1, 'a', 'b', 3) #p2 is a positional argument with default value? ab >>> f(1, p2='b') #p2 is a keyword argument? None b 

NTN!

+2
source share

I believe that calls a function with

 function(arg1="value") 

This will use the keyword keyword, but when defining a functional interface with

 def function(arg1="value"): 

you define a "default". ()

So, to answer your question; Having a default value after a positional argument is perfectly normal, and therefore invokes a keyword with an argument without a keyword.

Also note that when calling a function, you cannot have an argument without a keyword after the keyword.

+2
source share

All Articles