在列表理解中引发异常:无效的语法

时间:2019-03-06 10:03:01

标签: python-3.x syntax-error list-comprehension

要检查方法是否被正确调用,我想检查每个字符并使程序员不可能错误地使用该方法。因为该方法将在Web服务器中以return redirect(...)的形式调用,所以我想引发一个异常,而不是返回错误值(例如FalseNone)。

def redirect(uri):
    [raise ValueError('URI must be URL-encoded, ASCII only!') for c in uri if not (32 <= ord(c) <= 127)]

这给出了“无效语法”例外:

File "server.py", line 115
    [raise ValueError('URI must be URL-encoded, ASCII only!') for c in uri if not (32 <= ord(c) <= 127)]
         ^
SyntaxError: invalid syntax

我可以通过多种方式解决此问题,但我想知道:为什么不允许在列表理解中进行举报?

1 个答案:

答案 0 :(得分:1)

语法

从语法角度来看,您的答案在full grammar spec中。

$result = Model::whereIn('status_id', [1, 2, 3]) ->whereBetween('created_at', [$date_from, $date_to]) ->get(); $active_records = $result->where('status_id', 1); $pending_records = $result->where('status_id', 2); $closed_records = $result->where('status_id', 3); 终端仅出现在源自raise(声明)的规则中:

stmt

列表理解的第一部分是stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE small_stmt: (... | flow_stmt | ...) flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt raise_stmt: 'raise' [test ['from' test]] (布尔值或表达式)或teststar_expr):

*expr

重点是无法从atom: ... | '[' [testlist_comp] ']' | ... testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) (列表理解的左侧)派生一条语句。因此,您的表达在语法上是错误的。

语义

正如@Neb在评论中指出的那样,试图返回一个(test|star_expr)的列表理解没有意义。

您可能还记得raise是Python 2中的一条语句,并成为Python 3中的一个函数。

Python 2:

print

Python 3:

>>> [print(1) for _ in range(1)]
  File "<stdin>", line 1
    [print(1) for _ in range(1)]
         ^
SyntaxError: invalid syntax

列表理解现在在语法上是正确的。同样,没有语法规则会阻止您编写此代码:

>>> [print(1) for _ in range(1)]
1
[None]

但是语义仍然不清楚:您要执行操作(即使用功能的副作用)还是要建立列表?请记住,列表理解是功能语言的借用,尤其是我认为是Haskell。因此,他们不在这里执行操作。

我对@ answer”问题的Is it Pythonic to use list comprehensions for just side effects?引用@Mark Ransom的评论:

  

我会更进一步地指出,列表理解内的副作用是不寻常的,意外的,因此是邪恶的,即使您在完成操作时使用结果列表也是如此。 –马克·勒索姆

我使用以下经验法则:即使您使用结果,也要避免列表理解中的任何副作用