feature: **kwargs allowing improperly named variables

混江龙づ霸主 提交于 2019-11-28 08:41:40

问题


The following is invalid python:

def myInvalidFun(kw arg zero=6):
    pass

The following is valid python:

def myValidFun(**kwargs):
    if kwargs.has_key("kw arg zero"):
        pass

To call myValidFun, however, is tricky. For instance, the next few approaches do not work:

myValidFun(kw arg zero=6)      # SyntaxError: invalid syntax
myValidFun("kw arg zero"=6)    # SyntaxError: keyword can't be an expression

kwargs = dict("kw arg zero"=6) # SyntaxError: keyword can't be an expression 
myValidFun(**kwargs)

(Perhaps the identical errors to the last two hint at what happens under the hood?) This, however, DOES work:

kwargs = {"kw arg zero": 6}
myValidFun(**kwargs)

Is there a reason why, in particular, myValidFun("kw arg zero"=6) is not valid, in light of the {:} syntax for creating dictionaries?

(More background: I have a class which is much like a dictionary, only with significant amounts of validation, and an __init__ which builds a container using the entries of the dictionary, but is not a dictionary... it is actually an XML ElementTree, which is in some ways list-like and in others dict-like. The __init__ method must take keys like "my first element" and "my_first_element" and consider them different things. The class and __init__ work fine with **kwargs, but initializing my class is a multi-liner in the form of my example which does work, and seems like it could be simpler.)

edit: I understand the concept of identifiers, and my invalid code is there to make a point. I guess my question should be rephrased as:

Why is the following valid?:

myValidFun(**{"invalid identifier":6})

回答1:


Keywords to python functions must be valid identifiers. This is because on the other side, they need to be unpacked into identifiers (variables):

def foo(arg=3):
    print arg

most of the things you have are not valid identifiers:

kw arg zero  #Not valid identifier -- Can't have spaces
"kw arg zero" #Not valid identifier -- It's parsed as a string (expression)

Doing

dict("kw arg zero" = 6)

is no different to the parser than

myValidFunc("kw arg zero" = 6)

now as you've pointed out, You can pass things view mapping packing/unpacking (**kwargs). However, it can only be accessed through a dictionary.




回答2:


myInvalidFun(kw arg zero=6): is invalid because spaces are not allowed in identifiers.

myValidFun("kw arg zero"=6) is invalid because functions expect the keywords to be valid variable names not strings. Some thing like "kw arg zero"=6 is also invalid because you can't assign a value to a string.

dict("kw arg zero"=6) : Same as above. BTW dict() accepts (key,value) pairs or an iterable.

This is valid because you only passed a dict here and dicts can strings as key with spaces.

def myValidFun(**kwargs): #using ** here simply packs the dictionary again
        pass
myValidFun(**{"invalid identifier":6})

This is valid because you used a valid identifier in function definition

def myValidFun( foo = 5):  #foo from dict replaces it's default value
    print foo               #prints 6
myValidFun(**{"foo":6}) 

Invalid:

def myValidFun(foo bar = 5): # syntax error, invalid identifier
    print foo
myValidFun(**{"foo bar":6})    
    



回答3:


your key names cannot have spaces. by putting quotes around the argument in your function call, an expression is evaluated

try this

def myValidFun(**kwargs):
    if "kw_arg_zero" in kwargs:
        print kwargs["kw_arg_zero"]


myValidFun(kw_arg_zero="whatever")


来源:https://stackoverflow.com/questions/16700006/feature-kwargs-allowing-improperly-named-variables

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!