我不是一个真正的大python -但我发现这个语法一次,忘记从哪里来的,所以我想我应该记录它:
如果你使用sys.stdout.write而不是print(区别在于,sys.stdout.write接受圆括号内的函数参数-而print不接受),那么对于一行程序,你可以将命令和for的顺序颠倒,删除分号,并将命令括在方括号中,即:
python -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"
我不知道这个语法在Python中是如何调用的:)
一行中的方括号是“列表推导式”;在Python 2.7中注意这一点:
STR=abc
echo $STR | python -c "import sys,re; a=(sys.stdout.write(line) for line in sys.stdin); print a"
输出:
<generator object <genexpr> at 0xb771461c>
因此,圆括号/圆括号中的命令被视为“生成器对象”;如果我们通过调用next()来“迭代”它,那么括号内的命令将被执行(注意输出中的“abc”):
echo $STR | python -c "import sys,re; a=(sys.stdout.write(line) for line in sys.stdin); a.next() ; print a"
输出:
abc
<generator object <genexpr> at 0xb777b734>
如果我们现在使用方括号——注意我们不需要调用next()来执行命令,它会在赋值时立即执行;然而,后来的检查发现a是None:
echo $STR | python -c "import sys,re; a=[sys.stdout.write(line) for line in sys.stdin]; print a"
输出:
abc
[None]
这并没有留下太多的信息去寻找——对于方括号的情况——但我偶然发现了这一页,我认为它解释了:
Python技巧和技巧-第一版- Python教程| Dream.In.Code:
If you recall, the standard format of a single line generator is a kind of one line 'for' loop inside brackets. This will produce a 'one-shot' iterable object which is an object you can iterate over in only one direction and which you can't re-use once you reach the end.
A 'list comprehension' looks almost the same as a regular one-line generator, except that the regular brackets - ( ) - are replaced by square brackets - [ ]. The major advantage of alist comprehension is that produces a 'list', rather than a 'one-shot' iterable object, so that you can go back and forth through it, add elements, sort, etc.
实际上它是一个列表——只是它的第一个元素在执行时变成了none:
echo $STR | python -c "import sys,re; print [sys.stdout.write(line) for line in sys.stdin].__class__"
输出:
abc
<type 'list'>
echo $STR | python -c "import sys,re; print [sys.stdout.write(line) for line in sys.stdin][0]"
输出:
abc
None
列表推导式在5中另有说明。数据结构:5.1.4。列表推导式——Python v2.7.4文档“列表推导式提供了一种简洁的创建列表的方法”;据推测,这就是列表的有限“可执行性”在一行程序中发挥作用的地方。
好吧,希望我没有说得太离谱……
这里有一个单行命令行,包含两个非嵌套的for循环;两者都包含在“列表理解”方括号内:
echo $STR | python -c "import sys,re; a=[sys.stdout.write(line) for line in sys.stdin]; b=[sys.stdout.write(str(x)) for x in range(2)] ; print a ; print b"
输出:
abc
01[None]
[None, None]
注意,第二个“列表”b现在有两个元素,因为它的for循环显式地运行了两次;然而,sys.stdout.write()在这两种情况下的结果(显然)都是None。