list comprehension filtering - “the set() trap”

前端 未结 5 1310
野性不改
野性不改 2020-11-30 04:16

A reasonably common operation is to filter one list based on another list. People quickly find that this:

[x for x in list_1 if x          


        
5条回答
  •  没有蜡笔的小新
    2020-11-30 04:51

    So now I'm wondering - why can python 3.x optimize away the set literal to only build once, but not set(list_2)?

    No one's mentioned this issue yet: how do you know set([1,2,3]) and {1, 2, 3} are the same thing?

    >>> import random
    >>> def set(arg):
    ...     return [random.choice(range(5))]
    ... 
    >>> list1 = list(range(5))
    >>> [x for x in list1 if x in set(list1)]
    [0, 4]
    >>> [x for x in list1 if x in set(list1)]
    [0]
    

    You can't shadow a literal; you can shadow set. So before you can consider hoisting, you need to know not just that list1 isn't being affected, you need to be sure that set is what you think it is. Sometimes you can do that, either under restrictive conditions at compile time or more conveniently at runtime, but it's definitely nontrivial.

    It's kind of funny: often when the suggestion of doing optimizations like this comes up, one pushback is that as nice as they are, it makes it harder to reason about what Python performance is going to be like, even algorithmically. Your question provides some evidence for this objection.

提交回复
热议问题