【问题标题】:feature: **kwargs allowing improperly named variables功能:**kwargs 允许不正确命名的变量
【发布时间】:2013-05-22 19:24:11
【问题描述】:

以下是无效的python:

def myInvalidFun(kw arg zero=6):
    pass

以下是有效的python:

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

然而,打电话给myValidFun 很棘手。例如,接下来的几种方法不起作用:

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)

(也许与最后两个相同的错误暗示了幕后发生的事情?)但是,这确实有效:

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

根据用于创建字典的 {:} 语法,是否有原因,特别是 myValidFun("kw arg zero"=6) 无效?

(更多背景:我有一个很像字典的类,只有大量的验证,还有一个__init__,它使用字典的条目构建一个容器,但不是字典......它实际上是一个 XML ElementTree,它在某些方面类似于列表,而在其他方面类似于 dict。__init__ 方法必须采用“my first element”和“my_first_element”之类的键,并将它们视为不同的东西。类和@987654329 @ 与 **kwargs 一起工作正常,但初始化我的类是我的示例形式的多线程,它确实有效,而且看起来可能更简单。)

编辑:我理解标识符的概念,我的无效代码是为了说明这一点。我想我的问题应该改写为:

为什么以下有效?:

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

【问题讨论】:

  • 将数据作为关键字参数传递:data={ ... } 因为空格不能作为参数名称。
  • 这听起来像是一个更安全的主意。我的意思是,我知道最后一个有效的片段适用于我当前的 python 实现,但对我来说似乎有点粗略。感谢您的建议。

标签: python python-2.x


【解决方案1】:

python 函数的关键字必须是有效的标识符。这是因为另一方面,它们需要被解包成标识符(变量):

def foo(arg=3):
    print arg

您拥有的大多数东西都不是有效的标识符:

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

在做

dict("kw arg zero" = 6)

与解析器没有什么不同

myValidFunc("kw arg zero" = 6)

现在正如您所指出的,您可以传递事物视图映射打包/解包 (**kwargs)。但是,它只能通过字典访问。

【讨论】:

  • 是的,我明白了,虽然我没有想到 dict() 是一个接受 **kwargs 参数的函数,但现在这很有意义。但是为什么myValidFunc(**{"kw arg zero":6}) 有效呢?创建的结果字典有一个不是有效标识符的键,对吧?我仍然觉得我错过了一些明显的东西......
  • @EthanCoon -- 是的,它是一个无效的标识符,但是,它永远不能作为标识符在另一端被解包,只能作为kwargs 字典的一部分。
  • @EthanCoon -- 有趣的是,我在规范中找不到任何地方实际声明允许这种行为。我发现的最好的是here,它只讨论有效的标识符。这可能是依赖于实现的行为(但我需要搜索更多才能确定)。
  • 嗯,好的。 “它不在规范中,解释器的未定义行为也是如此,所以你很幸运”是我的一个好的回答。我会稍等一下,看看是否还有其他 cmets/answers,但如果你在答案中编辑了一些类似的内容,我会检查它。谢谢!
  • @EthanCoon -- 嗯......我会比这里更小心......“我在规范中找不到它”和“它是不在规范中”:-P.
【解决方案2】:

myInvalidFun(kw arg zero=6): 无效,因为identifiers 中不允许有空格。

myValidFun("kw arg zero"=6) 无效,因为函数期望关键字是有效的变量名而不是字符串。像"kw arg zero"=6 这样的东西也是无效的,因为你不能给字符串赋值。

dict("kw arg zero"=6) : 同上。 BTW dict() 接受(键、值)对或可迭代对象。

这是有效的,因为您在这里只传递了一个 dict,而 dicts 可以将字符串作为带有空格的键。

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

这是有效的,因为您在函数定义中使用了有效的标识符

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

无效:

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

【讨论】:

    【解决方案3】:

    您的键名不能有空格。 通过在你的函数调用中为参数加上引号,一个表达式被评估

    试试这个

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-11
      • 2011-05-29
      • 1970-01-01
      • 1970-01-01
      • 2018-11-13
      • 2021-08-02
      • 2021-06-29
      相关资源
      最近更新 更多