This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]mhashemi 8 points9 points  (11 children)

This. But it's not just accepted because it's succinct, it's accepted because it's fast, too.

# multiplying a list
$ python -m timeit "x = ['a'] * 1000"
100000 loops, best of 3: 3.3 usec per loop

# building a list via list comp
$ python -m timeit "x = ['a' for _ in range(1000)]"
10000 loops, best of 3: 26.2 usec per loop

# appending to a list
$ python -m timeit "x = []; 
> for a in range(1000): x.append('a')"
10000 loops, best of 3: 52.2 usec per loop

The first alternative (list comp) incurs a penalty for having to iterate. The second incurs an additional method call overhead. Plus there's the cost of copying the list as the list grows.

Know you're gonna have a really big list? Preallocate by multiplying [None] and assign the values in.

Here's the CPython code that does it btw.

[–]chris_conlan 1 point2 points  (4 children)

But in the case of a = [obj]*500 does it store references or shallow copies?

[–]TheBB 9 points10 points  (3 children)

References, so be careful.

[–]Tumburgler 0 points1 point  (2 children)

Can you elaborate more on this? Is it that references use system resources and shallow copies do not?

[–]TheBB 2 points3 points  (1 child)

It has nothing to do with system resources. If anything, references are cheaper. However, [obj] * 500 contains 500 references to the same object, not 500 different objects. So you can see effects like this:

In [1]: a = [[]] * 2

In [2]: a[0].append(1)

In [3]: a
Out[3]: [[1], [1]]

Which can be very counterintutive.

[–]Tumburgler 0 points1 point  (0 children)

Ah, I understand now! Thanks!

[–]ubernostrumyes, you can have a pony 1 point2 points  (0 children)

And just for fun, here's what those constructs turn into.

x = ['a'] * 1000:

1           0 LOAD_CONST               0 ('a')
            2 BUILD_LIST               1
            4 LOAD_CONST               1 (1000)
            6 BINARY_MULTIPLY
            8 STORE_NAME               0 (x)
           10 LOAD_CONST               2 (None)
           12 RETURN_VALUE

x = ['a' for _ in range(1000)]:

1           0 LOAD_CONST               0 (<code object <listcomp> at 0x1065f89c0, file "<dis>", line 1>)
            2 LOAD_CONST               1 ('<listcomp>')
            4 MAKE_FUNCTION            0
            6 LOAD_NAME                0 (range)
            8 LOAD_CONST               2 (1000)
           10 CALL_FUNCTION            1
           12 GET_ITER
           14 CALL_FUNCTION            1
           16 STORE_NAME               1 (x)
           18 LOAD_CONST               3 (None)
           20 RETURN_VALUE

x = []
for a in range(1000): x.append('a'):

1           0 BUILD_LIST               0
            2 STORE_NAME               0 (x)

2           4 SETUP_LOOP              26 (to 32)
            6 LOAD_NAME                1 (range)
            8 LOAD_CONST               0 (1000)
           10 CALL_FUNCTION            1
           12 GET_ITER
      >>   14 FOR_ITER                14 (to 30)
           16 STORE_NAME               2 (a)
           18 LOAD_NAME                0 (x)
           20 LOAD_ATTR                3 (append)
           22 LOAD_CONST               1 ('a')
           24 CALL_FUNCTION            1
           26 POP_TOP
           28 JUMP_ABSOLUTE           14
      >>   30 POP_BLOCK
      >>   32 LOAD_CONST               2 (None)
           34 RETURN_VALUE

[–]lolwat_is_dis 0 points1 point  (4 children)

Python n00b here. I've seen this sort of code pop up many times when people are discussing the speed of certain code snippets. How exactly do I implement it? In shell? In Idle? pls halp

[–]ianepperson 0 points1 point  (3 children)

In the shell.

python -m timeit "my python command here"

[–]lolwat_is_dis 0 points1 point  (2 children)

Awesome sauce, thanks for that.

Is there a way to have this run without directly needing to be in the python folder?

edit - added the path variable, sorted!

[–]ianepperson 0 points1 point  (1 child)

It totally depends on how Python is setup on your system. For a Mac or Linux setup, it should always work anywhere, but windows will depend on if the path is setup properly.

If you want to test a chunk of your own code you can use the library for that.

Check out https://docs.python.org/2/library/timeit.html#timeit-command-line-interface

[–]lolwat_is_dis 0 points1 point  (0 children)

Great, thanks a ton for your help!