[Python-ideas] Alternative spelling for list.append()

Steven D'Aprano steve at pearwood.info
Tue Jun 19 06:00:42 EDT 2018


On Mon, Jun 18, 2018 at 09:20:25PM -0400, Juancarlo Añez wrote:
> >> For all practical purpose, it would be enough to define that the
> >> expression:
> >>
> >> mylist += [item]
> >>
> >> gets optimized to mylist.append(item).

What if mylist doesn't have an append method?

Just because the variable is *called* "mylist" doesn't mean it actually 
is a list. Since Python is dynamically typed, the compiler has no clue 
ahead of time whether mylist is a list, so the best it could do is 
compile the equivalent of:

    if builtins.type(mylist) is builtins.list:
        call mylist.append(item)
    else:
        call mylist.__iadd__([item])


which I suppose it possible, but that's the sort of special-case 
optimization which CPython has avoided. (And when it has been tried, has 
often been very disappointing.)

Better to move the optimization into list.__iadd__, but doing that still 
pays the cost of making a one-item list. Now that's likely to be fast, 
but if the aim is to avoid making that one-item list (can you say 
"premature optimization"?) then it is a failure.

Besides, it's hardly worthwhile: += is already virtually as fast as 
calling append.

[steve at ando ~]$ python3.5 -m timeit -s "L = []" "L.append(1)"
1000000 loops, best of 3: 0.21 usec per loop

[steve at ando ~]$ python3.5 -m timeit -s "L = []" "L += [1]"
1000000 loops, best of 3: 0.294 usec per loop


[...]
> It seems that the optimization is already in place:

Not in 3.5 it isn't.


[steve at ando ~]$ python3.5 -c "import dis; dis.dis('L.append(1)')"
  1           0 LOAD_NAME                0 (L)
              3 LOAD_ATTR                1 (append)
              6 LOAD_CONST               0 (1)
              9 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             12 RETURN_VALUE


[steve at ando ~]$ python3.5 -c "import dis; dis.dis('L += [1]')"
  1           0 LOAD_NAME                0 (L)
              3 LOAD_CONST               0 (1)
              6 BUILD_LIST               1
              9 INPLACE_ADD
             10 STORE_NAME               0 (L)
             13 LOAD_CONST               1 (None)
             16 RETURN_VALUE


> import timeit
[...]

That times a large amount of irrelevant code that has nothing to do with 
either += or append.


-- 
Steve


More information about the Python-ideas mailing list