【问题标题】:Ternary operator in Python raises TypeError when using * operator on empty list?Python 中的三元运算符在空列表上使用 * 运算符时会引发 TypeError?
【发布时间】:2016-03-27 02:57:21
【问题描述】:

如果len(a) > 0,我想打印列表a 的内容,否则我想打印-1。这似乎很简单,但它引发了TypeError,指出a 是一个int,而不是一个序列,只有当a 是一个空列表时:

>>> a = [2]
>>> print(*a if len(a) > 0 else -1)
2 # as expected
>>> a = []
>>> print(*a)

>>> # It has no trouble evaluating *a when a is empty
... ### HERE IS THE ERROR:
...
>>> print(*a if len(a) > 0 else -1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: print() argument after * must be a sequence, not int
>>> ### But this works fine:
...
>>> if len(a) > 0:
...     print(*a)
... else:
...     print(-1)
...
-1

为什么会这样?

根据Python Documentation

表达式x if C else y 首先评估条件,C 而不是 比x。如果C 为真,则评估x 并返回其值; 否则,y 被评估并返回其值。

所以 *a 根本不应该被评估,但它会导致 TypeError?

我正在使用 Python 3.5

【问题讨论】:

    标签: list python-3.x ternary-operator


    【解决方案1】:

    我不是专家,但看看PEP 448,看起来* 语法不是通用表达式语法的一部分,但它特定于函数调用站点(以及其他东西,如元组和字典显示) . (这有点骇人听闻。)

    PEP 明确指出了一些他们禁止的类似语法,因为他们不知道应该做什么。不过,您的代码似乎没有经过特别考虑。

    函数调用中不带括号的推导,例如 f(x for x in it),已经有效。这些可以扩展到:

    f(*x for x in it) == f((*x for x in it))

    f(**x for x in it) == f({**x for x in it})

    但是,尚不清楚这是否是最佳行为 或者它是否应该解压缩到调用 f 的参数中。自从 这可能会令人困惑,并且只有非常边际的效用, 它不包含在本 PEP 中。相反,这些会抛出一个 应使用带显式括号的 SyntaxError 和理解 而是。

    我认为您的代码有效地解析为print(*(a if len(a) &gt; 0 else -1)),这就是为什么您会收到错误TypeError: print() argument after * must be a sequence, not int。相比之下,这是可行的:

    >>> print(*a if len(a) > 0 else ['nothing'])
    nothing
    

    【讨论】:

    • 非常有趣。我看到如果我改为写print(*[-1] if not a else a),它会打印出我想要的内容。既然我知道它是如何解析的,那么处理它应该不是问题。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2016-09-09
    • 1970-01-01
    • 2013-12-14
    • 2018-09-26
    • 2021-10-06
    • 2021-07-14
    • 2020-03-14
    相关资源
    最近更新 更多