Python reference to dictionary callback

I have a class that defines a set of callback functions (shown here as cb1well cb2). I save the map that I want to call after some event.

class Foo:
    cb1 = None
    cb2 = None

    def test(self, input):
        for (name, callback) in map:
            if name == input:
                if callback: callback()
                ...

    map = {'one':cb1, 'two':cb2}

def mycallback():
    print "mycallback()"

f = Foo()
f.cb1 = mycallback  # Register our callback
f.test('one')     # Nothing happens

Can you spot the problem?

What happens when a class is initialized, the values cb1and cb2(which both None) are copied to the map. Therefore, even after the user "registers" the callback (by assigning cb1), the value on the card is still Noneand nothing is called.

Since in Python there is no such thing as “by reference,” how do I fix this?

+5
source share
5 answers

?

import collections

class Foo(object):
    handlers = None

    def __init__(self):
        self.handlers = collections.defaultdict(set)

    def register(self, event, callback):
        self.handlers[event].add(callback)

    def fire(self, event, **kwargs):
        for handler in self.handlers.get(event, []):
            handler(**kwargs)

foo = Foo()
foo.register('one', mycallback)
foo.fire('one')
+9

. Foo:

def register(self, name, cb): self.map[name] = cb

:

f.cb1 = mycallback

:

f.register('one', mycallback)  
+1

.

class Delegate(object):
  def __get__(self, instance, owner):
    return instance._cbs.get(self, lambda x: None)

  def __set__(self, instance, value):
    if not hasattr(instance, '_cbs'):
      instance._cbs = {}
    instance._cbs[self] = value

  def __delete__(self, instance):
    if not hasattr(instance, '_cbs'):
      instance._cbs = {}
    instance._cbs[self] = lambda x: None

  def __hash__(self):
    return id(self)

class C(object):
  cb1 = Delegate()
  map = {'one': 'cb1'}

  def test(self, cb):
    getattr(self, self.map[cb])()

def foo():
  print 'bar!'

c = C()
c.cb1 = foo
c.test('one')
0

, , ? , .

:

class CallbackMap(object):
    pass

class Foo(object):
    callbacks = CallbackMap()

    def test(self, input):
        callback = getattr(Foo.callbacks, input)
        if callback: callback()

# setup defaults
Foo.callbacks.one = None
Foo.callbacks.two = some_default_callback

# customize
def mycallback():
    print "mycallback()"

f = Foo()
Foo.callbacks.one = mycallback  # Register our callback
f.test('one') # works
0

, Python " ". None , . , . , map . callback_names = ['cb1', 'cb2'], getattr(self, callback_name)() . , map = {'one': 'cb1', 'two': 'cb2'}.

- , .

-1

All Articles