【问题标题】:Why are unparanthesized tuples in generators not allowed in the expression field?为什么在表达式字段中不允许生成器中的非括号元组?
【发布时间】:2016-03-22 07:31:55
【问题描述】:
# why is the following invalid
x = (k, v for k, v in some_dict.items())

# but if we wrap the expression part in parentheses it works
x = ((k, v) for k, v in some_dict.items())

我浏览了文档,似乎没有找到任何关于此的内容?什么可能会混淆语法不允许的解析器?尽管有更复杂的工作:

# k, v somehow confuses the parser but this doesnt???
x = ('%s:%s:%s' % (k, v, k) for k, v in some_dict.items())

那为什么我们不需要用周围的括号包裹%s:%s:%s % (k, v, k)

【问题讨论】:

    标签: python python-3.x syntax generator


    【解决方案1】:

    x = (k, v for k, v in some_dict.items())

    x = (k, v for k, v in some_dict.items())
    x = ((k, v) for k, v in some_dict.items())
    x = (k, (v for k, v in some_dict.items()))
    

    需要括号来消除歧义。

    x = ('%s:%s:%s' % (k, v, k) for k, v in some_dict.items()) 也需要括号:

    x = ('%s:%s:%s' % k, v, k for k, v in some_dict.items())
    x = ('%s:%s:%s' % k, (v, k) for k, v in some_dict.items())
    x = ('%s:%s:%s' % (k, v, k) for k, v in some_dict.items())
    

    碰巧你已经有足够的括号来解决其中的歧义,使其能够以预期的方式运行。

    【讨论】:

      【解决方案2】:

      Python 的解析器会解析这个

      x =  (k, v for k, v in some_dict.items())
      

      作为包含k 和生成器表达式的元组:

      v for k, v in some_dict.items()
      

      但这不是一个有效的生成器表达式:它必须是,正如PEP 289 所说:

      直接在一组括号内,两边不能有逗号

      Python在这里看到的生成器不是直接在一组括号内,并且确实在一边有一个逗号,所以它是非法的。


      之所以这样认为是因为解析器(故意)非常简单。特别是,它是一个 LL(1) 解析器,意思是:

      • 从左到右扫描令牌;
      • 考虑当前令牌和下一个令牌(一个前瞻令牌);和
      • 尽快决定表达式的含义

      因此,它得到当前标记为k,并看到下一个是逗号。这是一个元组,它坚持这个决定。它只会在稍后看到for(当当前标记为v 时),因此它成为元组inside 的生成器表达式。解析器不会回溯以查看是否存在对表达式的潜在合法解析(存在 - 您打算将元组放在生成器表达式中的那个,但可能并不总是存在),它只是立即抛出错误。

      【讨论】:

      • 为什么v for k, v in some_dict.items() 不是一个有效的生成器表达式?我看不出有什么问题。
      • @Wombatz 看到 PEP 的引用;要构建一个值和一个 genexp 的元组,您必须将 genexp 包装在另一组括号中。断章取义,那个 genexp 很好,但在这种情况下,它是一个错误。这就像您将它用作函数的参数并传递一些其他参数一样 - 您可以使用sum(f(x) for x in ...),但必须使用sum((f(x) for x in ....), start='')
      • “断章取义,那个 genexp 没问题”。这就是我的意思,谢谢你的澄清。似乎表达式本身无效。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-19
      • 2017-12-18
      • 2018-10-09
      • 2021-11-24
      相关资源
      最近更新 更多