List comprehension rebinds names even after scope of comprehension. Is this right?

后端 未结 6 2074
清酒与你
清酒与你 2020-11-22 04:03

Comprehensions are having some unexpected interactions with scoping. Is this the expected behavior?

I\'ve got a method:

def leave_room(self, uid):
           


        
6条回答
  •  孤独总比滥情好
    2020-11-22 04:50

    Yes, list comprehensions "leak" their variable in Python 2.x, just like for loops.

    In retrospect, this was recognized to be a mistake, and it was avoided with generator expressions. EDIT: As Matt B. notes it was also avoided when set and dictionary comprehension syntaxes were backported from Python 3.

    List comprehensions' behavior had to be left as it is in Python 2, but it's fully fixed in Python 3.

    This means that in all of:

    list(x for x in a if x>32)
    set(x//4 for x in a if x>32)         # just another generator exp.
    dict((x, x//16) for x in a if x>32)  # yet another generator exp.
    {x//4 for x in a if x>32}            # 2.7+ syntax
    {x: x//16 for x in a if x>32}        # 2.7+ syntax
    

    the x is always local to the expression while these:

    [x for x in a if x>32]
    set([x//4 for x in a if x>32])         # just another list comp.
    dict([(x, x//16) for x in a if x>32])  # yet another list comp.
    

    in Python 2.x all leak the x variable to the surrounding scope.


    UPDATE for Python 3.8(?): PEP 572 will introduce := assignment operator that deliberately leaks out of comprehensions and generator expressions! It's motivated by essentially 2 use cases: capturing a "witness" from early-terminating functions like any() and all():

    if any((comment := line).startswith('#') for line in lines):
        print("First comment:", comment)
    else:
        print("There are no comments")
    

    and updating mutable state:

    total = 0
    partial_sums = [total := total + v for v in values]
    

    See Appendix B for exact scoping. The variable is assigned in closest surrounding def or lambda, unless that function declares it nonlocal or global.

提交回复
热议问题