Why doesn’t kwargs accept a keyword? [keyword can’t be an Expression]

Asked

Viewed 147 times

1

In python there is the kwargs, that makes things so much easier when I need to name parameters. define the attributes of an element that I will create with this function I have a function where the second parameter I use a kwargs. However, when I pass the keyword class by parameter an error is generated.

Example:

create_element_tag('tag', 'class'='x')]

Exit:

keyword can’t be an Expression

Example:

create_element_tag('tag', class='x')

Exit:

Syntaxerror: invalid syntax

But I really need an attribute whose index contains that name.

How could I solve this problem on python?

  • Hello, You can’t pass key words from language as it says to documentation. It is necessary to change approach.

1 answer

2

It is not possible to properly understand what you are calling "kwargs" - but rather, in Python it is possible to specify optional arguments in a function and select the arguments by keyword - this is what we call "keyword arguments":

def conectar(host, porta=80, timeout=None):
    # [corpo da função]

conectar("http://...", timeout=10)

In the above example, we use the standard value of the (80) port that is in the function definition, and send as second parameter the timeout value - specifying that "keyword argument" in the function call. - From what I understand this is what you’re calling "kwargs".

At no point, in Python, can you write a keyword that is a "statement" as a variable name - or as a parameter name. So you can’t have arguments with the name of def, for, while or class. This is a syntax error. Ex.:

def funcao(while=1):
   pass

class is the keyword used to define classes - so it is reserved. Some of Python’s built-in (built-in) names can be redefined, and used as the name of variables at will - they usually denote classes or functions, which however use they have, do not have a special treatment of language: list, id, type, etc....

Now - Python does have a Mechanism that allows the parameters for a function to be passed as data, and not set to full in the code: prefixing the name of a parameter with two asterisks in the definition of a function, causes any unknown parameters to be received within a dictionary, which is assigned to that parameter. In general, the name of this dictionary is kwargs or kw - but this is just a convention.

In [1]: def ve_parametros(**kw):
   ...:     print(kw)
   ...:     

In [2]: ve_parametros(a=5, b=6)
{'b': 6, 'a': 5}

Note above that the "a" and "b" parameters used in the function call become "kw" dictionary keys - which can be treated as common strings within the function.

Only this still does not allow you to use keywords in calling the function -

In [3]: ve_parametros(class=5)                                                                                                                                                    
  File "<ipython-input-3-62829ca1a227>", line 1                                                                                                                                   
    ve_parametros(class=5)                                                                                                                                                        
                      ^                                                                                                                                                           
SyntaxError: invalid syntax     

However, there is the analog mechanism - if you, in the call of a function, prefix a dictionary with two asterisks, the keys and values of the dictionary will be used as keyword argumetns within that function:

In [4]: def recebe_parametros(a, b, c):
   ...:     print ("a: {}, b: {}, c: {}".format(a, b, c))
   ...:                                                                                                                                                                           

In [5]: params = {"c": 3, "b": 2, "a": 1}

In [6]: recebe_parametros(**params)                                                                                                                                               
a: 1, b: 2, c: 3  

So if you use the ** both to create the parameters of your function and to receive them, you can have parameters with the keyword name - which will be treated exclusively as strings (but they can never be fixed in the code):

In [8]: def reserved_params(**kw):
...:     if "class" in kw:
...:         print("Recebi o parâmetro 'class': {}".format(kw["class"]))
...:         

In [9]: reserved_params(**{"class": "parametro proibido"})
Recebi o parâmetro 'class': parametro proibido

If you need the name class Because its function, for example, is giving output to a snippet of html,and the function already accepts variable parameters, this solution should be enough - just use the "class" phrase as a dictionary key in the call anyway. If it is a popular library that mounts html this way, it is most likely to accept some "class" -like name that is automatically converted to class function output - names like klass, class_ or cls usually used. I recommend you refer to the documentation of the html generator which, it seems to me, you are using.

And finally, this way of passing keywords is not the best solution: if automatic parameters are used, in general one should not try to use keywords as variable names: the resources of passing and receiving parameters dynamically per dictionary lend themselves to a myriad of other things - and, as Python is not much of an exception, it is possible to do this. Because if the parameter name is passed as a string in a dictionary and consumed as a string within the function, the language has no reason to treat it as a variable name in an intermediate stage , and thus throw a syntax error: can use keywords as in the above examples, although this is not the purpose of the variable parameters.

  • You can specify what you mean by "specify"? :)

  • "Specify" - was a "big" typing error (I ate a syllable and invented a hundred)

  • 1

    I didn’t want to edit it myself. As this is a bit monotonous here was a way to promote some iteration. I take this opportunity to congratulate you on the answer. I’ll delete my comments if you think it’s okay to delete yours.

  • Don’t even leave it there! :-)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.