Python: Referring to a list comprehension in the list comprehension itself?

╄→гoц情女王★ 提交于 2020-12-16 07:19:47

问题


This thought just came to my mind. Say for whatever reason you wanted to get the unique elements of a list via a list comprehension in Python.

[i if i in {created_comprehension} else 0 for i in [1, 2, 1, 2, 3]

[1, 2, 0, 0, 3]

I dunno, I don't really have a purpose for this but it'd be cool if it was possible to refer to the comprehension as it's being created.

(e.g. How to remove duplicate items from a list using list comprehension? is a similar question)


回答1:


Disclaimer: this is purely speculation on my part, and I don't have data to back it up

I don't think you can refer to a list comprehension as it is being built. Python will first have to create the list, allocate memory or it, and add elements to it, before it binds it to a variable name. Therefore, I think you'll end up with a NameError if you try to refer to the list, while it's being built in a list-comp

You might ultimately, therefore, want a set to hold your uniques, and build your list from there (Oh God! this is hacky):

In [11]: L = [1, 2, 1, 2, 3]

In [12]: s = set(L)

In [13]: answer = [sub[0] for sub in [(i,s.remove(i)) if i in s else (0,0) for i in L]]

In [14]: answer
Out[14]: [1, 2, 0, 0, 3]

In [15]: s
Out[15]: set()



回答2:


Disclaimer: this is just an experiment. I compare a list comprehension and a list inside a list comprehension.

I want x to contain elements from [1,2,1,2,3,4,5] only if those elements are in this list comprehension [e for e in range(3,6)] which should be [3,4,5]

x = [i for a in [e for e in range(3,6)] for i in [1,2,1,2,3,4,5] if i == a]

The output is right:

[3, 4, 5]



回答3:


I'll assume i in {created_comprehension} was meant to be i not in {created_comprehension}. At least that's what the data suggests.

So here's a fun horrible abuse that I wouldn't trust to always work. Mainly to demonstrate that the argument "it's impossible because it's not yet assigned" is wrong. While the list object indeed isn't assigned yet, it does already exist while it's being built.

>>> import gc
>>> [i if i not in self else 0
     for ids in [set(map(id, gc.get_objects()))]
     for self in [next(o for o in gc.get_objects() if o == [] and id(o) not in ids)]
     for i in [1, 2, 1, 2, 3]]
[1, 2, 0, 0, 3]

This gets the ids of all objects tracked for garbage collection before the new list gets created, and then after it got created, we find it by searching for a newly tracked empty list. Call it self and then you can use it. So the middle two lines are a general recipe. I also successfully used it for this question, but it got closed before I could post.

A nicer version:

>>> [i if i not in self else 0
     for old in [ids()] for self in [find(old)]
     for i in [1, 2, 1, 2, 3]]
[1, 2, 0, 0, 3]

That used these helper functions:

def ids():
    import gc
    return set(map(id, gc.get_objects()))

def find(old):
    import gc
    return next(o for o in gc.get_objects() if o == [] and id(o) not in old)


来源:https://stackoverflow.com/questions/33665504/python-referring-to-a-list-comprehension-in-the-list-comprehension-itself

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!