pyc08_cback

Embed Size (px)

Citation preview

  • 8/9/2019 pyc08_cback

    1/18

    ©2008 Google -- [email protected]

    Don't call us, we'll call you: callback patterns and idioms in Python

    http://www.aleax.it/pyc08_cback.pdf 

    1Sunday, March 9, 2008

    http://www.aleax.it/py4prog.pdfhttp://www.aleax.it/py4prog.pdf

  • 8/9/2019 pyc08_cback

    2/18

    Audience levels for this talk

    2

    Shu

    Ha

    Ri

    ("Retain")

    ("Detach")

    ("Transcend")2Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    3/18

    The "Callback" conceptit's all about library/framework code that"calls back" into YOUR code

    rather than the "traditional" (procedural)approach where YOU call code supplied as

    entry points by libraries &c"the Hollywood principle": "don't call us,we'll call you"

    coinage: Richard E. Sweet, in "The Mesa Programming

    Environment", SigPLAN Notices, July 1985for: customization (flexibility) and "event-driven"architectures ("lightweight concurrency")

    33Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    4/18

    "Callback" implementationgive "somebody" a callablethe "somebody" may store it "somewhere"

    a container, an attribute, whateveror even just keep it as a local variable

    and calls it "when appropriate"when it needs some specific functionality(i.e., for customization)

    or, when appropriate events occur (statechanges, user actions, network or otherI/O, timeouts, system events, ...)

    44Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    5/18

    Customization

    55Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    6/18

    Customizing sort (by key)mylist.sort(key=str.toupper)

    handily, speedily embodies the DSU pattern:

    def DSU_sort(mylist, key):

      aux = [ (key(v), j, v)  for j, v in enumerate(mylist)]

      aux.sort()

      mylist[:] = [v for k, j, v in aux]

    Note that a little "workaround" is needed wrt theusual "call a method on each object" OO idiom...

    66Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    7/18

    OO customizing: the TM DP"Template Method" Design Pattern: performthe callbacks by "self delegation":class TMparent(object):

    ...self.somehook()...

    and customize by inheriting & overriding:class TMchild(TMparent):

    ...def somehook(self):...

    handy, compact, sometimes a bit rigidhttp://video.google.com/videoplay?docid=-5434189201555650834 and http://www.aleax.it/goo_pydp.pdf (49ff) for more

    77Sunday, March 9, 2008

    http://www.aleax.it/goo_pydp.pdfhttp://www.aleax.it/goo_pydp.pdfhttp://video.google.com/videoplay?docid=-5434189201555650834http://video.google.com/videoplay?docid=-5434189201555650834http://www.aleax.it/goo_pydp.pdfhttp://www.aleax.it/goo_pydp.pdfhttp://www.aleax.it/goo_pydp.pdfhttp://www.aleax.it/goo_pydp.pdfhttp://video.google.com/videoplay?docid=-5434189201555650834http://video.google.com/videoplay?docid=-5434189201555650834http://video.google.com/videoplay?docid=-5434189201555650834http://video.google.com/videoplay?docid=-5434189201555650834

  • 8/9/2019 pyc08_cback

    8/18

    Customizing schedulingsched needs TWO callback functionalities:

    what time is it right now?wait (sleep) until time T

    the OO way (more structured):import times=sched(time)

    the FP way (more flexible):

    s=sched(time.time, time.sleep)you might supply default callbacks, or not(Dependency Injection DP & variants)

    88Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    9/18

    Events

    99Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    10/18

    Kinds of "Event" callbacksthe Observer/Observable design patternGUI frameworks (mouse, keyboard, ...)asynchronous (event-driven) I/O (net &c)"event-driven" parsing (SAX &c)

    "scheduled" callbacks (sched)"concurrent" callbacks (threads &c)timing and debugging (timeit, pdb, ...)

    "system-event" callbacks

    1010Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    11/18

    The Observer DP

    11

    a "target object" lets you add "observers"could be simple callables, or objects

    when the target's state changes, it callsback to "let the observers know"

    design choices: "general" observers(callbacks on ANY state change), "specific"observers (callbacks on SPECIFIC statechanges; level of specificity may vary),"grouped" observers (objects with >1methods for kinds of state-change), ...

    11Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    12/18

    Callback issueswhat arguments are to be used on the call?

    no arguments: simplest, a bit "rough"in Observer: pass as argument the targetobject whose state just changed

    lets 1 callable observe several targetsor: a "description" of the state changes

    saves "round-trips" to obtain them

    other: identifier or description of eventbut -- what about other arguments (relatedto the callable, not to the target/event)...?

    1212Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    13/18

    Fixed args in callbacksfunctools.partial(callable, *a, **kw)

    pre-bind any or all argumentshowever, note the difference...:

    x.setCbk(functools.partial(f, *a, **kw))

    vsx.setCbk(f, *a, **kw)

    ...having the set-callback itself accept (and

    pre-bind) arguments is far neater/handiersombunall1 Python callback systems do that

    131: Robert Anton Wilson

    13Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    14/18

    Callback "dispatching"what if more than one callback is set for asingle event (or, Observable target)?

    remember and call the latest one onlysimplest, roughest

    remember and call them allLIFO? FIFO? or...?how do you _remove_ a callback?

    can one callback "preempt" others?can events (or state changes) be "grouped"?

    use object w/methods instead of callable

    1414Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    15/18

    Callbacks and Errorsare "errors" events like any others?or are they best singled-out?http://www.python.org/pycon/papers/deferex/

    Twisted Matrix's "Deferred" pattern: one

    Deferred object holds...N "chained" callbacks for "successes" +M "chained" callbacks for "errors"

    each callback is held WITH opt *a, **kwplus, argument for "event / erroridentification" (or, result of previouscallback along the appropriate "chain")

    1515Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    16/18

  • 8/9/2019 pyc08_cback

    17/18

    System-events callbacksfor system-events:

    atexit.register(callable, *a, **k)oldhandler = signal.signal(signum, callable)sys.displayhook, sys.excepthook,

    sys.settrace(callable)readline.set_startup_hook,set_pre_input_hook, set_completer

    1717Sunday, March 9, 2008

  • 8/9/2019 pyc08_cback

    18/18

    Q & Ahttp://www.aleax.it/pyc08_cback.pdf

    18

    ?  !18S d M h 9 2008

    http://www.aleax.it/py4prog.pdfhttp://www.aleax.it/py4prog.pdf