Search code examples
pythonfunctional-programminglate-binding

Dynamically Change Self Binding


In Javascript, bind, call, and apply allow you to change the reference to this on demand. I'm looking at a situation in Python where the code would look a bit nicer if I were able to do this instead of using getattr.

I'd like to pass a reference to a method, but change the instance the method refers to within a thread. In Javascript, I'd like to do this:

function produce (x) {
   enqueue(this.api.delete.bind(this.api, x))
}

function consume () { 
   api = new API()
   task = dequeue()
   task.call(api)
}

In Python, I have to do this:

def produce(self, x):
   enqueue(partial(self.api.delete, x))

def consume(self):
   api = API()
   task = dequeue() # callable
   ?????????

This may look a little odd, but what's going on is each api instance is running on a separate thread. getattr works, but I would prefer to pass verbs instead of nouns to the queue.


Solution

  • You can enqueue a lambda closing over x and waiting for its api instance:

    enqueue(lambda api: api.delete(x))
    

    And later just pass the API object:

    task = dequeue()
    task(api)
    

    You also can get an "unbound method reference" in Python 3, to which you can later pass self, by simply naming the class member:

    >>> class A:
    ...    def foo(self, x):
    ...       print(x)
    ... 
    >>> f = A.foo
    >>> f(A(), 1)  # equivalent to A().foo(1)
    1
    >>> f
    <function A.foo at 0x7f86c9b872f0>
    

    (IIRC, it will behave the same in Python 2, but the type of f will be something special.)