[英]Why doesn't this list comprehension do what I expect it to do?
The original list project_keys = sorted(projects.keys())
is [101, 102, 103, 104, 105, 106, 107, 108, 109, 110]
where the following projects were deemed invalid
this year: 108, 109, 110. 原始列表
project_keys = sorted(projects.keys())
是[101, 102, 103, 104, 105, 106, 107, 108, 109, 110]
,其中以下项目今年被视为invalid
:108,109,110 。
Thus: 从而:
for project in projects.itervalues():
# The projects dictionary is mapped to the Project class
if project.invalid:
# Where invalid is a Bool parameter in the Project class
project_keys.remove(project.proj_id)
print project_keys
This will return a list of integers (which are project id's) as such: 这将返回一个整数列表(项目ID为):
[101, 102, 103, 104, 105, 106, 107]
Sweet. 甜。
Now, I wanted it try the same thing using a list comprehension. 现在,我希望它使用列表理解尝试相同的事情。
project_keys = [project_keys.remove(project.proj_id) for project in projects.itervalues() if project.invalid
print project_keys
This returns: 返回:
[None, None, None]
So I'm populating a list with the same number as the removed elements but they're None
s? 所以我填充的列表与删除的元素具有相同的数字,但它们是
None
?
Can someone point out what I'm doing wrong? 有人可以指出我做错了吗?
Additionally, why would I use a list comprehension over the for-if
block at the top? 另外,为什么我会使用列表理解而不是顶部的
for-if
块? Conciseness? 简明? Looks nicer?
看起来更好?
Your list comprehension works using side-effects. 您的列表理解使用副作用。 Just executing it should update project_keys to give the result you want.
只是执行它应该更新project_keys以提供您想要的结果。
[project_keys.remove(project.proj_id)
for project in projects.itervalues()
if project.invalid]
The return value from remove
is None
. remove
的返回值为None
。 Assigning the result of the list comprehension to project_keys
is where you are going wrong. 将列表
project_keys
的结果分配给project_keys
是您出错的地方。
A simple loop is probably clearer here though. 一个简单的循环可能在这里更清楚。 A list comprehension that uses side-effects can be confusing.
使用副作用的列表理解可能会令人困惑。
However you can solve your problem in a slightly different way: 但是,您可以稍微不同的方式解决您的问题:
project_keys = sorted(project.proj_id
for project in projects.itervalues()
if not project.invalid)
This keeps the projects you are interested in, instead of removing those that you're not interested in. The example I gave above uses a generator expression instead of a list comprehension, but it would work with either. 这会保留您感兴趣的项目,而不是删除您不感兴趣的项目。上面给出的示例使用生成器表达式而不是列表推导,但它可以使用。
You, sir, have misunderstood list comprehensions. 先生,您误解了列表理解。
I want to remove all project ids that are invalid.
我想删除所有无效的项目ID。
project_keys = [project_keys.remove(project.proj_id)
for project in projects.itervalues() if project.invalid]
dummy = []
for project in projects.itervalues():
if project.invalid:
dummy.append(project_keys.remove(project.proj_id)) #what are you
project_keys = dummy #removing items from?
del dummy
mapped-fun = lambda project: project_keys.remove(project.proj_id)
filtering-fun = lambda project: project.invalid
project_keys = map(mapped-fun, filter(filtering-fun, projects.itervalues()))
As you can see, list comprehensions are not syntactical sugar around for
loops. 正如您所看到的,列表推导不是围绕
for
循环的语法糖。 Rather, list comprehensions are syntactical sugar around map()
and filter()
: apply a function to all items in a sequence that match a condition and get a list of results in return. 相反, 列表推导是围绕
map()
和filter()
语法糖 :将函数应用于与条件匹配的序列中的所有项,并获得返回的结果列表 。
Here, by function it is actually meant a side-effect-free transformation of input into output. 在这里,通过功能,它实际上是指输入到输出的无副作用转换。 This means that you "cannot" use methods that change the input itself, like
list.sort()
; 这意味着你“不能”使用改变输入本身的方法,如
list.sort()
; you'll have to use their functional equivalents, like sorted()
. 你必须使用它们的功能等价物,比如
sorted()
。
By "cannot", however, I don't mean you'll get error messages or nasal demons ; 但是,“不能”,我并不是说你会得到错误信息或鼻子恶魔 ; I mean you are abusing the language.
我的意思是你在滥用这种语言。 In your case, the evaluation of the list comprehension that happens as you assign it to a variable does indeed produce the intended side-effects -- but does it produce them on the intended variables?
在您的情况下,在将变量分配给变量时对列表理解的评估确实会产生预期的副作用 - 但它是否会在预期变量上产生它们?
See, the only reason why this can execute without an error is that before this list comprehension, there was another list called project_keys
and it's that list you are actually changing! 看,这可以在没有错误的情况下执行的唯一原因是,在此列表理解之前,还有另一个名为
project_keys
的列表,而这个列表实际上正在改变!
Lists comprehensions are a result of functional programming, which rejects side effects. 列表理解是函数式编程的结果,它拒绝副作用。 Keep that in mind when using lists comprehensions.
使用列表推导时请记住这一点。
So here's a thought process you can use to actually get the list comprehension you wanted. 所以这是一个思考过程,你可以用来实际获得你想要的列表理解。
I want all project ids that are valid (= not invalid.)
我想要所有有效的项目ID(=无效。)
dummy = []
for project in projects.itervalues():
if not project.invalid:
dummy.append(project.proj_id)
project_keys = dummy
del dummy
mapped-fun = lambda project: project.proj_id
filtering-fun = lambda project: not project.invalid
project_keys = map(mapped-fun, filter(filtering-fun, projects.itervalues()))
project_keys = [project.proj_id for project in projects.itervalues()
if not project.invalid]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.