empty lists vs empty generators
Bengt Richter
bokr at oz.net
Mon May 2 21:49:54 EDT 2005
On 2 May 2005 16:14:57 -0700, brian at mirror.org (Brian Roberts) wrote:
>I'm using using generators and iterators more and more intead of
>passing lists around, and prefer them. However, I'm not clear on the
>best way to detect an empty generator (one that will return no items)
>when some sort of special case handling is required.
>
>Typical code for handling an empty list:
> if somelist:
> for x in somelist:
> something(x)
> else:
> empty_list_special_case
>
>But this doesn't work with iterators -- a generator is "true"
>regardless of whether its going to return any items. (I understand
>why).
>
>The closest equivalent I know of is:
> n = 0
> for n, x in enumerate(somegenerator()):
> something(x)
> if n == 0:
> empty_list_special_case
>
>Which seems rather awkward -- doesn't read as easily for me, and
>introduces another variable.
And, if I understood the intent, doesn't work ;-)
>>> n = 0
>>> for n, x in enumerate(c for c in 'a'):
... print 'something', x
...
something a
>>> if n == 0:
... print 'empty list special case ??'
...
empty list special case ??
You could have used n = -1 as a sentinel that enumerate would not set,
but using a guaranteed-unique sentinel, you don't need enumerate, e.g.,
>>> x = sentinel = object()
>>> for x in (c for c in 'a'):
... print 'something', x
...
something a
>>> if x is sentinel:
... print 'empty list special case ??'
...
(nothing printed there)
and for the actually empty sequence
>>> x = sentinel = object()
>>> for x in (c for c in ''):
... print 'something', x
...
>>> if x is sentinel:
... print 'empty list special case ??'
...
empty list special case ??
>
>Q1: Is there a better or alternate way to handle this?
>Q2: Is there a way that handles both lists and generators, so I don't
>have to worry about which one I've got?
>
UIAM this should work for any iterable. You don't have to manufacture
a locally bound sentinel as above. You could pick anything to preset
the for-target that you know is not going to be produced by the iterable,
though you might need to use '==' instead of 'is' depending on your choice.
But e.g., I don't think I'd write
x = Exception # weird sentinel choice
for x in mystring:
print x, ord(x)
if x is Exception:
print 'null sequence'
None probably works well a lot of the time, but not always.
Similarly ''. Seems like a builtin sentinel binding like sentinel = object()
might be handy to standardize usage.
Regards,
Bengt Richter
More information about the Python-list
mailing list