为什么这个列表理解没有达到我预期的效果?

发布于 2024-09-03 16:45:08 字数 933 浏览 2 评论 0原文

原始列表 project_keys = Sorted(projects.keys())[101, 102, 103, 104, 105, 106, 107, 108, 109, 110] 其中今年以下项目被视为无效:108、109、110。

因此:

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

这将返回一个整数列表(项目 ID),如下所示:

[101, 102, 103, 104, 105, 106, 107]

甜蜜。

现在,我希望它使用列表理解尝试同样的事情。

project_keys = [project_keys.remove(project.proj_id) for project in projects.itervalues() if project.invalid  

print project_keys

这将返回:

[None, None, None]

因此,我使用与已删除元素相同的编号填充列表,但它们是 None

有人可以指出我做错了什么吗?

此外,为什么我要在顶部的 for-if 块上使用列表理解?简明?看起来更好看?

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.

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:

[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 Nones?

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? Conciseness? Looks nicer?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

淡写薰衣草的香 2024-09-10 16:45:08

您的列表理解使用副作用进行工作。只需执行它就应该更新 project_keys 以给出您想要的结果。

[project_keys.remove(project.proj_id)
 for project in projects.itervalues()
 if project.invalid]

remove 的返回值为 None。将列表理解的结果分配给 project_keys 是错误的地方。

不过,这里一个简单的循环可能会更清晰。使用副作用的列表理解可能会令人困惑。

但是,您可以以稍微不同的方式解决您的问题:

project_keys = sorted(project.proj_id
                      for project in projects.itervalues()
                      if not project.invalid)

这会保留您感兴趣的项目,而不是删除您不感兴趣的项目。上面给出的示例使用生成器表达式而不是列表理解,但它可以与任何一个一起使用。

Your list comprehension works using side-effects. Just executing it should update project_keys to give the result you want.

[project_keys.remove(project.proj_id)
 for project in projects.itervalues()
 if project.invalid]

The return value from remove is None. Assigning the result of the list comprehension to project_keys is where you are going wrong.

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.

铁憨憨 2024-09-10 16:45:08

先生,您误解了列表理解。

你可能想要什么(用文字表达)

我想删除所有无效的项目 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()))

正如您所看到的,列表推导式不是 for 循环周围的语法糖。相反,列表推导式是围绕 map()filter() :将函数应用于序列中与条件匹配的所有项目,并获取返回的列表结果。

这里,函数实际上是指输入到输出的无副作用转换。这意味着您“不能”使用更改输入本身的方法,例如 list.sort();您必须使用它们的等效功能,例如 sorted()

然而,我所说的“不能”并不意味着您会收到错误消息或 鼻恶魔;我的意思是你在滥用语言。在您的情况下,当您将列表理解分配给变量时发生的评估确实会产生预期的副作用 - 但它是否会在预期的变量上产生副作用?

看,它可以执行而不会出现错误的唯一原因是,在此列表理解之前,有另一个列表称为project_keys,它就是那个列表你真的在改变!

列表推导式是函数式编程的结果,它拒绝副作用。使用列表推导式时请记住这一点。


因此,您可以使用以下思考过程来实际获得所需的列表理解。

你真正想要什么(用言语)

我希望所有项目 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]

You, sir, have misunderstood list comprehensions.

What you probably wanted (in words)

I want to remove all project ids that are invalid.

What you wrote

project_keys = [project_keys.remove(project.proj_id)
                for project in projects.itervalues() if project.invalid]

What is actually going on

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                                            

What is actually going on (now with more "functional")

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. 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.

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(); you'll have to use their functional equivalents, like 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!

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.

What you actually wanted (in words)

I want all project ids that are valid (= not invalid.)

What you actually wanted

dummy = []
for project in projects.itervalues():
  if not project.invalid:
    dummy.append(project.proj_id)
project_keys = dummy
del dummy

What you actually wanted (now with more functional)

mapped-fun = lambda project: project.proj_id
filtering-fun = lambda project: not project.invalid
project_keys = map(mapped-fun, filter(filtering-fun, projects.itervalues()))

What you actually wanted (now as a list comprehension)

project_keys = [project.proj_id for project in projects.itervalues()
                if not project.invalid]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文