如何在一行中编写带条件的for循环

How to write for loop with condition in one line

原代码如下:

import site; 
import re 

for i in site.getsitepackages():
    package = re.search("^/usr/local/lib/.*/dist-packages$", i)
    if package is None:
        continue
    print(package.string)

输出:

/usr/local/lib/python3.8/dist-packages

这是一行代码:

import site; import re; for i in site.getsitepackages(): package = re.search("^/usr/local/lib/.*/dist-packages$", i); if package is None: continue; print(package.string)

输出:

  File "/tmp/ipykernel_2984/3719293883.py", line 1
    import site; import re; for i in site.getsitepackages(): package = re.search("^/usr/local/lib/.*/dist-packages$", i); if package is None: continue; print(package.string)
                            ^
SyntaxError: invalid syntax

我想把上面的多行转换成一行,然后在bash命令行中运行它:

python3 -c "<one line python code>"

为什么单行?它会影响可读性。

只需使用 heredoc:

python3 <<!
import site;
import re

for i in site.getsitepackages():
     package = re.search("^/usr/local/lib/.*/dist-packages$", i)
     if package is None:
         continue
     print(package.string)
!

虽然可以使用分号将某些 python 行连接在一起,但不能使用循环来实现。参见 this answer

Because the Python grammar disallows it. See the documentation:

stmt_list ::= simple_stmt (";" simple_stmt)* [";"]

Semicolons can only be used to separate simple statements (not >compound statements like for). And, really, there's almost no >reason to ever use them even for that. Just use separate lines. >ython isn't designed to make it convenient to jam lots of code >onto one line.

但是,对于 运行 一个带有 python -c 的循环,您可以 运行 它跨越多行。例如,下面的命令在单独的行中打印出数字 0 - 9:

python -c 'while i in range(10):
    print(i)
'

问题出在 for 命令上,该命令不允许与 ; 运算符一起使用,也不允许在 Python 中与多个 : 运算符一起使用。

有几种方法可以使这类事情顺利进行,但最简单的方法是巧妙地使用列表理解。

import re, site; [print(package.string) for i in site.getsitepackages() if (package := re.search("^/usr/local/lib/.*/dist-packages$", i))]

您可以从 bash 执行,例如:

pyhton3 -c 'import re, site; [print(package.string) for i in site.getsitepackages() if (package := re.search("^/usr/local/lib/.*/dist-packages$", i))]'

以上利用了 print(package.string) 仅在 if 为真时才执行的事实。它还利用了 := "walrus" in-place 赋值运算符,它的工作方式与普通 = 类似,只是您可以在公式或列表理解中使用它。

如果在 fully-fledged bash 脚本中,您也可以使用此处的文档。

python3 <<!
import re
import site
for i in site.getsitepackages():
    if package := re.search("^/usr/local/lib/.*/dist-packages$", i):
        print(package.string)
!

最后你可以使用 in-line 来自 bash 的换行符:

python -c $'import re, site\nfor i in site.getsitepackages():\n if package := re.search("^/usr/local/lib/.*/dist-packages$", i):\n  print(package.string)'

当您将 $ 放在 single-quoted 字符串前面时,bash 将扩展反斜杠转义换行符和其他反斜杠转义符。 (尽管将其与正则表达式结合使用时要小心!)