#350 · Classes · Advanced · 120 XP · about 25 min
User interfaces, games and servers are full of events: a button is clicked, a file is saved, a player scores. An event emitter lets parts of a program listen for events without knowing who raises them. Build an Emitter class.
on(event, listener) registers the function listener for the event named event. The same listener can be registered more than once, and is then called once per registration.once(event, listener) registers listener for the next emit of event only.off(event, listener) removes the earliest registration of listener for event (made by on or once) and returns True, or returns False if there is none. Listeners are compared with ==, so off('e', obj.method) finds a registration of obj.method.emit(event, *args) calls every listener registered for event with *args, in the order they were registered, and returns how many listeners it called.listener_count(event) returns how many registrations event has.Listeners may call on, once, off and emit themselves while an emit is running, so the rules are exact:
emit starts, it takes the list of registrations for the event as it is at that moment. It calls exactly those, in order, even if a listener adds or removes registrations during the emit. Such changes only affect later emits.once are removed when an emit of their event starts, before any listener is called.em = Emitter() log = [] em.on('save', lambda name: log.append('backup ' + name)) em.once('save', lambda name: log.append('first save of ' + name)) em.emit('save', 'notes.txt') # returns 2 em.emit('save', 'todo.txt') # returns 1 log # ['backup notes.txt', 'first save of notes.txt', 'backup todo.txt']
First solves only, ranked by stars and then time.