Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are the keys of a kwargs argument to Python function guaranteed to be type string?

def func(**kwargs):
   for key, value in kwargs.items():
      # Is key always going to be a string?
      # Could it have spaces?
      pass

Two questions about kwargs in Python.

  1. Is every key of kwargs guaranteed to be of type str? If so, I can avoid type checking.
  2. If #1 is true, would every key be guaranteed to not have spaces?
like image 221
engineerchuan Avatar asked Sep 11 '19 22:09

engineerchuan


3 Answers

A keyword argument passed directly must be a valid Python identifier, and yes it will always be treated as strings. Anything else is a SyntaxError.

f(foo=1) # Works
f($=1) # Fails
f(1=1) # Fails

Although, you can also give keyword arguments through unpacking. In this case, your keyword arguments must be strings still, but they can take any format.

Let's define a dummy function to test this.

def f(**kwargs):
    print(kwargs)

A keyword argument can contain a space or be a string of digits. It can even contain special characters.

f(**{"hello world": 'foo'}) # prints {'hello world': 'foo'}
f(**{"1": 'foo'}) # prints {'1': 'foo'}
f(**{"$": 'foo'}) # prints {'$': 'foo'}

A keyword argument must be a string. Anything else is a TypeError.

f(**{1: 'foo'}) # TypeError: f() keywords must be strings
f(**{b'foo': 1}) # TypeError: f() keywords must be strings
like image 108
Olivier Melançon Avatar answered Nov 15 '22 08:11

Olivier Melançon


The keywords in kwargs should follow the rules of variable names, full_name is a valid variable name (and a valid keyword), full name is not a valid variable name (and not a valid keyword).

From PEP 362 -- Function Signature Object:

A Parameter object has the following public attributes and methods:
name : str
- The name of the parameter as a string. Must be a valid python identifier name (with the exception of POSITIONAL_ONLY parameters, which can have it set to None.)

And, from the Docs:

2.3. Identifiers and keywords:
... Within the ASCII range (U+0001..U+007F), the valid characters for identifiers are the same as in Python 2.x: the uppercase and lowercase letters A through Z, the underscore _ and, except for the first character, the digits 0 through 9. ...

like image 37
MrGeek Avatar answered Nov 15 '22 08:11

MrGeek


Others have already covered the practical side of this, but I wondered if the documentation actually made any guarantees about keyword dictionaries' types.

The documentation on call semantics does not specifically say keyword arguments will have type str in the dictionary.

This is all that the documentation says about the type of the value of keyword arguments passed to a parameter declared with **:

a dictionary containing the excess keyword arguments (using the keywords as keys and the argument values as corresponding values), or a (new) empty dictionary

So, theoretically, it appears that the documentation allows you to recieve keyword arguments as bytes, but this does not occur in any current implementation of Python 3.

(For Python 2, the same holds, but for unicode instead of bytes.)

like image 21
jirassimok Avatar answered Nov 15 '22 06:11

jirassimok