简体   繁体   English

在空列表上使用*运算符时,Python中的三元运算符引发TypeError?

[英]Ternary operator in Python raises TypeError when using * operator on empty list?

I want to print the contents of a list a if len(a) > 0 , but otherwise I want to print -1 . 如果len(a) > 0 ,我想打印列表a的内容,否则我想打印-1 This seems to be pretty simple, but it's raising a TypeError , stating that a is an int, not a sequence, only when a is an empty list: 这似乎很简单,但是它引发了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

Why is this the case? 为什么会这样呢?

According to the Python Documentation : 根据Python文档

The expression x if C else y first evaluates the condition, C rather than x . x if C else y首先计算条件C而不是x If C is true, x is evaluated and its value is returned; 如果C为true,则对x求值并返回其值; otherwise, y is evaluated and its value is returned. 否则,将评估y并返回其值。

So *a shouldn't be getting evaluated at all, and yet it's causing a TypeError? 所以*a根本不应该得到评估,但是会导致TypeError?

I'm using Python 3.5 我正在使用Python 3.5

I'm not an expert, but looking at PEP 448 it looks like this * syntax isn't part of the general expression syntax, but it's specific to function callsites (and other things like tuple and dictionary displays). 我不是专家,但是从PEP 448来看,它看起来像*语法不是通用表达式语法的一部分,但是它特定于函数调用站点(以及其他类似元组和字典显示的内容)。 (It's a bit of a hack.) (有点hack。)

The PEP explicitly calls out some similar syntax that they've forbidden because they didn't know what it should do. PEP明确调用了一些他们已禁止的类似语法,因为他们不知道该怎么做。 It doesn't look like your code has been particularly considered though. 看起来您的代码似乎并未得到特别考虑。

Unbracketed comprehensions in function calls, such as f(x for x in it), are already valid. 函数调用中的方括号式理解(例如f(x中的x表示))已经有效。 These could be extended to: 这些可以扩展为:

f(*x for x in it) == f((*x for x in it)) f(* x用于其中的x)== f((* x用于其中的x))

f(**x for x in it) == f({**x for x in it}) f(** x表示x的值)== f({** x表示x的值})

However, it wasn't clear if this was the best behaviour or if it should unpack into the arguments of the call to f. 但是,尚不清楚这是否是最好的行为,还是应该将其分解为对f的调用的参数。 Since this is likely to be confusing and is of only very marginal utility, it is not included in this PEP. 由于这可能会造成混淆,并且仅具有很小的效用,因此它不包含在此PEP中。 Instead, these will throw a SyntaxError and comprehensions with explicit brackets should be used instead. 相反,它们将引发SyntaxError,而应使用带有括号的理解。

I think your code is effectively parsing as print(*(a if len(a) > 0 else -1)) , which is why you then get the error TypeError: print() argument after * must be a sequence, not int . 我认为您的代码有效地解析为print(*(a if len(a) > 0 else -1)) ,这就是为什么TypeError: print() argument after * must be a sequence, not int错误TypeError: print() argument after * must be a sequence, not int原因,它TypeError: print() argument after * must be a sequence, not int By comparison, this works: 相比之下,这有效:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM