在python列表中添加额外语句
我需要在文本文件中找到一行,该行包含一个特定的字符串,然后将该行及其后面的所有行附加到列表中。我就是这样完成的在python列表中添加额外语句,python,list-comprehension,Python,List Comprehension,我需要在文本文件中找到一行,该行包含一个特定的字符串,然后将该行及其后面的所有行附加到列表中。我就是这样完成的 file1 = open("input.txt", "r") always_print = False lines = file1.readlines() output = [] for line in lines: if always_print or "def set" in line: #def set is the string i want outp
file1 = open("input.txt", "r")
always_print = False
lines = file1.readlines()
output = []
for line in lines:
if always_print or "def set" in line: #def set is the string i want
output.append(line)
always_print = True
虽然这很好,但我尝试使用列表理解来做同样的事情。这就是我得到的:
lines = [ item.strip() for item in open("input.txt")]
always_print = False
output = [item for item in lines if "def set" or print_always in item]
这显然不起作用,因为当找到所需的字符串时,我没有设置always_print=True。我如何在列表中做到这一点 编辑更正我之前完全不正确的答案: 这并不是说我会在生产代码中使用它,而是黑客攻击它,你可以在列表中使用它
always_print = []
output = [item for item in lines
if always_print
or (always_print.append(1) if ("def set" in item) else None)
or "def set" in item]
只是解释一下,三个条件中的第二个总是返回None
,这是一个错误的值
如果您不想对项目中的“def set”进行两次评估,请进一步滑入黑暗面:
always_print = []
output = [item for item in lines
if always_print
or (
(always_print.append(1) or True) if ("def set" in item) else False
)]
Edit2
如果我更详细地描述这里发生的事情
上面的代码(以及凯文在评论中提到的代码)使用了三种不同的技巧
False
,任何其他数字为True
。同样,空列表为False
,而非空列表的计算结果为True
a_list.append(x)
是一个函数调用,返回None
,其计算结果为False
。它还有一个副作用,就是将新元素x
添加到a_列表的末尾
和
和或
这样的逻辑运算符的求值顺序是从左到右和
在第一个False
值处停止执行,而或
在第一个True
值处停止执行,可用于根据特定条件控制是否执行列表追加。三元运算符“x if y else z”也有求值顺序,但先求值“y”,然后求值“x”或“z”,但决不能同时求值dropwhile
用于查找包含def集合的第一行:
from itertools import dropwhile
output = list(dropwhile(lambda l: 'def set' not in l, lines))
dropwhile()
将跳过行中与测试不匹配的任何条目;一旦匹配,它就会停止测试,并简单地从那里产生所有结果
dropwhile()
返回迭代器;我在这里使用了list()
将其转换为行列表,但您也可以将其用作另一个循环的基础,如换行符的剥离等
演示:
中途退出可能是最好的解决方案。但是,如果你想要一些真正别致的东西,请看以下内容:
使用列表理解,您可以使用简单的检查和转换,但您应该看到列表理解更像一个数学映射。但是,您可以将用于测试某个项目是否应包含在某种状态中的函数指定为某种状态,即让您的检查记住是否已经发生了某些事情。使其成为函子(或函数对象):
哪些产出:
[6, 7, 8, 9]
[4, 5, 6, 7, 8, 9]
@说实话,我只是读了一下output=…
行…你不能把句子(比如你的作业always\u print=True
)放在列表理解中。那么这会像原始代码那样在循环中修改always\u print
值吗?有趣的方法。我的想法是一样的:output=[line for line in line如果总是打印或“def set”in line而不是总是打印。append(1)]
。使用大致相同的“条件突变”原理。啊,这更优雅,以一种黑暗的方式。凯文和森普拉德..试图理解..总是打印。附加(1)做什么?“打印”是否始终不是布尔值?我们可以像列表一样附加到它吗?这真的很好。这正是我所需要的。所以,为了理解,我可以得出结论,python不支持列表理解中的额外语句吗?@Amistad Correct。列表理解是一个表达式,任何表达式都不能包含语句。@Amistad:在Python中,列表理解是一个表达式。表达式可以任意嵌套,但语句是顶级组件,不能嵌套在彼此内部或表达式中。赋值是一个语句,您不能在表达式中使用它。@Amistad:您必须使用另一个可变对象,它的状态可以通过方法更改,但很快就会变糟。这里,一个dropwhile()
更好地表达了发生的事情。
class Drop_before:
def __init__(self, val):
self.val = val
self.always_print = False
def __call__(self, current_val):
if current_val == self.val:
self.always_print = True
return self.always_print
drop_before_6 = Drop_before(6)
print [x for x in xrange(10) if drop_before_6(x)]
#using filter
print filter(Drop_before(4), xrange(10))
[6, 7, 8, 9]
[4, 5, 6, 7, 8, 9]