Editor

Event Emitter

#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:

  • When 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.
  • Registrations made with once are removed when an emit of their event starts, before any listener is called.

Examples

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']

Constraints

  • Event names are strings; listeners are functions or bound methods
  • Up to 10,000 registrations for one event and 100,000 listener calls in a test

Fastest solvers

Leaderboard

First solves only, ranked by stars and then time.