Noob questions about Python

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Thu Oct 18 19:08:28 EDT 2007


On Wed, 17 Oct 2007 23:06:24 -0700, Ixiaus wrote:

> I know '<<' is shifting x over by n bits; but could you point me to some
> literature that would explain why it is the same as "x*2**n"? (Googling
> only returns bit shift, but doesn't necessarily explain the manner in
> which you are using it)

In decimal, multiplying by ten shifts the digits to the left by one place:

31 * 10 => 310
310 * 10 => 3100
3100 * 10 => 31000

In binary, multiplying by two shifts the bits to the left by one place:

101 * 10 => 1010
1010 * 10 => 10100
10100 * 10 => 101000

Because the underlying numbers are the same regardless of what base we 
use to write it in, bit-shifts to the left are equivalent to repeated 
multiplication by two regardless of the display base. Hence:

>>> 7 << 1
14
>>> 14 << 1
28
>>> 28 << 1
56

or to do it another way:

>>> 7 << 3  # multiplication by 2**3
56



Similarly, a bit-shift to the right is equivalent to dividing by two and 
dropping any remainder.



> I will have to read up more on Generators, but maybe you can give me a
> lowdown on why
> sum([1 << k for k, i in enumerate(reversed(val)) if int(i)]) is less
> efficient than using a Generator (is the generator a 'temporary' list?)
> sum(1 << k for k, i in enumerate(reversed(val)) if int(i))

The list comprehension:

[1 << k for k, i in enumerate(reversed(val)) if int(i)]

creates the entire list first. That potentially can require a lot of 
memory, leading to all sorts of complicated memory shuffles as the list 
is resized, paging, etc. 

Using a generator expression means that you avoid creating the entire 
list all in one go. That saves you memory, which may mean that you save 
time.

However, for small sets of input, it is likely that the overhead of 
creating the generator in the first place outweighs the saving of not 
creating the whole list.

The definition of "small" depends on what you are trying to do. In my 
tests, I have found that sum(list comprehension) is marginally faster 
than sum(generator expression) even for 10,000 items.


-- 
Steven



More information about the Python-list mailing list