func(*args, **kwargs, x) throwing invalid syntax - python

Studied myself into a corner again...
def superfunction(*args, **kwargs, k):
^
SyntaxError: invalid syntax
Whats the rule Im breaking here? It seems that youre not supposed to mix 'regular' variables with * variables, but I cant find anyone to confirm or deny this. I read somewhere (and I cant find in now of course) that some types of arguments have to come first, I believe keyword arguments, which may or may not be part of my issue.

Try this:
def superfunction(k, *args, **kwargs):
The **kwargs variable keyword parameter must be the last part in the function declaration. Second-to-last, the *args variable position parameter. (In Python 3.x only, you can also have keyword-only parameters between *args and **kwargs.) And in the first places, the positional parameters - that's the correct way to declare function parameters. Take a look at this post for additional details.
For the full reference, see the Function definitions section in Python 3.x or Python 2.x.

Syntax should be like this:
def superfunction(k, *args, **kwargs):
First you give all the positional arguments, then non-keyword arguments, and then keyword arguments.

Related

What is the general signature of a function in python 3.8 or 3.8+?

I have not been able to find a good place that I can refer to to help myself understand a general function signature in python 3.8 or +. I want to understand a general syntax that includes position only, keywords only, *args, **kwargs and all.
I am able to reason about everything but I cannot seem to fir *args into the general signature.
def inc(a:int, b:int,/, c:int=10, d:int=5, *, e:int=15,f:int=3, **kwargs) -> int:
return None
In this no matter where I place *args it throws a syntax error. I can remove ,*, (the keyword-only-after-this indicator) and then *args seems to fit in nicely
Can you please help me understand how *args fit in with position only and keywords only elements of a function signature and what a general syntax for a python function is supposed to look like
You can't use both a varargs argument and the special * argument to indicate keyword-only arguments after positional arguments. PEP-3102, which introduced the keyword-only syntax, says:
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.
(emphasis mine).
You can either have * or *args, but not both. The point of the special * argument is to allow you to have keyword-only arguments when you don't already have a varargs argument.
* is not "the keyword-only-after-this indicator". Non-** arguments listed after a * argument are keyword-only. For example, in the following function:
def f(*args, x):
...
x is keyword-only.
If you don't want your function to take *args, you can use a bare * to mark the start of keyword-only arguments, but if you do want *args, then keyword-only arguments go after that.

How to use count method (string class)?? in python [duplicate]

I am having trouble figuring out the arguments to csv.dictreader and realized I have no clue what the square brackets signify.
From the docmentation:
class csv.DictReader(csvfile[, fieldnames=None[, restkey=None[, restval=None[, dialect='excel'[, *args, **kwds]]]]])
I'd appreciate a summary of the arguments to the class instantiation.
Thanks
The square brackets indicate that these arguments are optional. You can leave them out.
So, in this case you are only required to pass the csvfile argument to csv.DictReader. If you would pass a second parameter, it would be interpreted as the fieldnames arguments. The third would be restkey, etc.
If you only want to specify e.g. cvsfile and dialect, then you'll have to name the keyword argument explicitly, like so:
csv.DictReader(file('test.csv'), dialect='excel_tab')
For more on keyword arguments, see section 4.7.2 of the tutorial at python.org.
Usually in api documentation square brackets mean optional. I would think they mean the same here.
This is actually a subset of the widely used notation to unambiguously describe language syntax called Backus-Naur Form (see Wikipedia article for details).
To reiterate what the others have said, the arguments are optional.
If you leave out optional parts, the remaining fieldnames=, restval=, restkey= or dialect= keywords tell the function which parts are missing.
The syntax doesn't suggest it, but I wouldn't be surprised if the keywords allow the arguments to be specificied in any order, except that the last two arguments must be either both specified, or both omitted.

Defining function in Python accepts (x, *args), but not (*args, x). Why?

I have recently begun teaching myself Python and I have an inquiry regarding defining functions. I read about the *args and **args possibilites in functions and decided to try them out. I tried to make a very simple calculator by trying to make this function in IDLE:
def test(*args, tool):
total = 0
if(tool == '+' or tool == 'plus'):
for a in args:
total += a
return total
However, when I got passed the first line, Python threw this error at me:
SyntaxError: invalid syntax
At first, I didn't know what I did wrong, so I tried to type() them both and realized that *args is a tuple and **args is a dictionary. So I understood how Python would be confused when trying to convert a string of letters into a tuple and then finding what might be the tool part of the code.
However, when I switched place on the *args and tool: def test(tool, *args), I wasn't met with any errors at all and the code ran as expected (strangely, without the tool parameter at all). However, when I tried to call the function this way: test(4, 2, 3, 'tool'), it once again threw an error at me, complaining about how it can't add together ints and strings.
What is going on?
*args must be at the end of a function call. This is because if there are arguments after *args, Python has no way of knowing when *args ends and the rest of the arguments begin. If there are a set number of arguments at the start, then *args, it knows to stop at the end of the function.
Python is an interpreted language, so it will read the function from left to right and assign variables as it goes. Take the following:
def foo(bar, *args):
print("Hello, world!", bar, args)
If I pass in foo(3, 4, 5, 6) Python says, "Okay, we'll set bar to 3. Then, the rest of our arguments go into args. That's (4, 5, 6)".
Now with the arguments the other way round:
def foo(*args, bar):
print("Hello, world!", bar, args)
With the same arguments, Python will say, "The rest of the arguments can be put into args. That's (3, 4, 5, 6). Wait, what about bar? We have nothing left!" And so it throws an error.
With your function, test, you can't input three numbers and a string if you're adding up *args. You have to pass tool in first, then the numbers.
It is just because of the interpreter (or compiler in other languages' cases). When you define a function the interpreter looks for arguments, then extra arguments, and then keyword arguments; for properly explaining:
In this case, the interpreter will find just one argument:
def (myArg):
In this case, the interpreter will find an argument and 'remaining' arguments, so it knows how to map the first argument and then the others.
def (myArg, *args):
But in this case, the interpreter looks for a list of arguments so it will take all of them and pack them into args; what happens to myArg then?
def(*args, myArg):
There are no more arguments because it already packed all of them into args, just because the interpreter doesn't know when args ends.

Python keyword args vs kwargs

This might be a simple question:
Is there any difference between the two folowing:
def myfunc(a_list = [], **kwargs):
my_arg = kwargs.get('my_arg', None)
pass
and
def myfucn(a_list = [], my_arg = None):
pass
If not, which would be considered more pythonic?
Thanks,
-Matt
For a simple function, it's more Pythonic to explicitly define your arguments. Unless you have a legit requirement to accept any number of unknown or variable arguments, the **kwargs method is adding unnecessary complexity.
Bonus: Never initialize a list in the function definition! This can have unexpected results by causing it to persist because lists are mutable!
The first one can take virtually any keyword arguments provided (regardless of the fact that it only uses one of them), whereas the second can only take two. Neither is more Pythonic, you simply use the one appropriate for the task.
Also, the second is not "keyword arguments" but rather a "default value".
The second alternative allows my_arg to be passed as a positional rather than a keyword argument. I would consider it unpythonic to declare **kwargs when you don't actually use them for anything.

Using named arguments with variable length un-named arguments in Python

I apologize if this question has already been asked/answered, I would have expected that to be the case but was unable to find any related questions...
I'd like to create a python function that takes two mandatory arguments, one named argument, and some unknown number of other, non-named arguments as so:
def my_function(arg1, arg2, arg3=None, *other_args):
pass
Is this possible in Python 2.x?
Can a function accept named arguments in addition to a variable length argument list?
I believe the answer is 'no', in which case I'm thinking the only solution available to me would be something similar to the following:
def my_function(arg1, arg2, **kwargs):
arg3 = kwargs["arg3"]
other_args = kwargs["other_args"]
Is that correct?
That syntax is certainly valid, but I think you mean can you write the function signature such that arg3 is only bound if it's used as a named parameter (e.g. my_function(1, 2, arg3 = 3)), and otherwise to have all arguments past the first two be caught by *other_args, in which case the answer is no. Optional arguments can be specified by naming, but they're also positional like normal arguments and are filled in if enough parameters are available, before resorting to catch-alls like *args or **kwargs.
I would probably write it exactly as you did, using keyword arguments

Categories

Resources