I'm an organizer for Boston Python, and we like to raffle off books at events. I've got a technique I like for doing it. Here it is recorded for posterity.

We use meetup.com to handle RSVPs for events. I have a small program that queries the meetup.com API for people who have RSVP'd "yes" to an event. I use it to get a list of names, then I shuffle the names, make an iterator, then pick names off it. I do this on the big screen in an interactive prompt:

>>> import random
>>> from attendees import yes
>>> people = yes(120746442)     # The event number from meetup.com
>>> len(people)
174
>>> random.shuffle(people)      # Give them a good shake
>>> pick = iter(people)         # Make an iterator
>>> print next(pick)            # Now pick people!
Ned Batchelder
>>> print next(pick)
Jessica McKellar
>>> print next(pick)
Jason Michalski
>>> # etc...
>>>

Iterables like the list of people's names are usually iterated completely with a for loop or a list comprehension. But you can step them one item at a time if you like. iter() creates an iterator from an iterable (confusing, I know...), then you can use next() to get the next item from the iterable.

There aren't many reasons to use iterators like this, but occasionally it can be useful.

tagged: » 8 reactions

Comments

[gravatar]
Christopher Svec 3:04 AM on 26 Sep 2013

Hmm... the winners seem a bit suspicious, better double check on your randomizer. :-)

[gravatar]
Ned Batchelder 10:37 AM on 26 Sep 2013

It could happen! :)

[gravatar]
Christos Kontas 11:40 AM on 26 Sep 2013

Nice and elegant, simple technique! Only I can't understand why attendes.yes() does not produce an iterable (list, generator, tuple, etc.) on the first place!

[gravatar]
Matt Behrens 11:51 AM on 26 Sep 2013

Christos: a list is iterable, but it is not an iterator. At least in 2.7. ;)

>>> l = [1, 2, 3]
>>> type(l)
<type 'list'>
>>> next(l)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list object is not an iterator
>>> i = iter(l)
>>> type(i)
<type 'listiterator'>
>>> next(i)
1

[gravatar]
Vincent Driessen 12:58 PM on 26 Sep 2013

How can everyone be sure that the attendees module does not monkey-patch random's shuffle function? ;-)

[gravatar]
Dominik Wronski 1:35 PM on 26 Sep 2013

Nice program. I am the host of Wroclaw Python and we mainly use facebook fanpage and facebook events. When I found a time I will post similiar program using facebook API ;)

[gravatar]
Mike 2:47 PM on 26 Sep 2013

Is there a reason you don't use random.sample ()? IIRC, random.shuffle () is not able to create all possible permutations.

[gravatar]
Ned Batchelder 4:35 PM on 26 Sep 2013

@Mike: There are a few reasons:

1) Random.sample isn't as good for picking people, since the second sample could pick the same person again. Not a big deal, easily dealt with.

2) I like that this technique shows off a little-traveled area of Python knowledge.

3) For the same reason that random.shuffle can't produce all possible permutations, neither can repeated calls to random.sample: the set of all possible permutations or sampling sequences is larger that the set of all possible random generator states. So using sample won't fix the problem. Luckily, it isn't much of a problem, since we're only going to pick a handful of names anyway.

Add a comment:

name
email
Ignore this:
not displayed and no spam.
Leave this empty:
www
not searched.
 
Name and either email or www are required.
Don't put anything here:
Leave this empty:
URLs auto-link and some tags are allowed: <a><b><i><p><br><pre>.