Why is it valid to assign to an empty list but not to an empty tuple?

前端 未结 4 1027
长发绾君心
长发绾君心 2020-11-30 10:02

This came up in a recent PyCon talk.

The statement

[] = []

does nothing meaningful, but it does not throw an exception either. I ha

4条回答
  •  庸人自扰
    2020-11-30 10:29

    “Assigning to a list” is the wrong way to think about it.

    In all cases you are unpacking: The Python interpreter creates an unpacking instruction from all three ways to write it, there are no lists or tuples involved on the left hand side (code courtesy of /u/old-man-prismo):

    >>> def f():
    ...     iterable = [1, 2]
    ...     a, b = iterable
    ...     (c, d) = iterable
    ...     [e, f] = iterable
    ...
    >>> from dis import dis
    >>> dis(f)
      2           0 LOAD_CONST               1 (1)
                  3 LOAD_CONST               2 (2)
                  6 BUILD_LIST               2
                  9 STORE_FAST               0 (iterable)
    
      3          12 LOAD_FAST                0 (iterable)
                 15 UNPACK_SEQUENCE          2
                 18 STORE_FAST               1 (a)
                 21 STORE_FAST               2 (b)
    
      4          24 LOAD_FAST                0 (iterable)
                 27 UNPACK_SEQUENCE          2
                 30 STORE_FAST               3 (c)
                 33 STORE_FAST               4 (d)
    
      5          36 LOAD_FAST                0 (iterable)
                 39 UNPACK_SEQUENCE          2
                 42 STORE_FAST               5 (e)
                 45 STORE_FAST               6 (f)
                 48 LOAD_CONST               0 (None)
                 51 RETURN_VALUE      
    

    As you can see, all three statements are exactly the same.

    What unpacking does now is basically:

    _iterator = iter(some_iterable)
    a = next(_iterator)
    b = next(_iterator)
    for superfluous_element in _iterator:
        # this only happens if there’s something left
        raise SyntaxError('Expected some_iterable to have 2 elements')
    

    Analoguously for more or less names on the left side.

    Now as @blckknght said: The compiler for some reason checks if the left hand side is an empty tuple and disallows that, but not if it’s an empty list.

    It’s only consistent and logical to allow assigning to 0 names: Why not? You basically just assert that the iterable on the right hand side is empty. That opinion also seems to emerge as consensus in the bug report @gecko mentioned: Let’s allow () = iterable.

提交回复
热议问题