Assigning generator expressions to ctype arrays
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Thu Oct 27 18:31:45 EDT 2011
On Thu, 27 Oct 2011 13:34:28 -0700, Patrick Maupin wrote:
> Bug or misunderstanding?
>
> Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53) [GCC 4.5.2] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>>>> x = 32 * [0]
>>>> x[:] = (x for x in xrange(32))
>>>> from ctypes import c_uint
>>>> x = (32 * c_uint)()
>>>> x[:] = xrange(32)
>>>> x[:] = (x for x in xrange(32))
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> ValueError: Can only assign sequence of same size
>From the outside, you can't tell how big a generator expression is. It
has no length:
>>> g = (x for x in xrange(32))
>>> len(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'generator' has no len()
Since the array object has no way of telling whether the generator will
have the correct size, it refuses to guess. I would argue that it should
raise a TypeError with a less misleading error message, rather than a
ValueError, so "bug".
The simple solution is to use a list comp instead of a generator
expression. If you have an arbitrary generator passed to you from the
outside, and you don't know how long it is yourself, you can use
itertools.islice to extract just the number of elements you want. Given g
some generator expression, rather than doing this:
# risky, if g is huge, the temporary list will also be huge
x[:] = list(g)[:32]
do this instead:
# use lazy slices guaranteed not to be unexpectedly huge
x[:] = list(itertools.islice(g, 32))
--
Steven
More information about the Python-list
mailing list