Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Python distinguish callback function which is a member of a class?

Tags:

python

Please look at the simple example:

class A:   def __init__(self, flag):     self.flag = flag    def func(self):     print self.flag  a = A(1) b = A(2) callback_a = a.func callback_b = b.func  callback_a() callback_b() 

The result is:

1 2 

It runs as expected. But I have a question. In C, the callback function is passed as a pointer. In Python, it should have a similar way to do this, so the caller knows the address of the function. But in my example, not only the function pointer is passed, but also the parameter (self) is passed, because the same method of the same class prints different results. So my questions are:

  1. Does such a method in Python only has one copy in memory? My meaning is that the code of any method only has one copy, and in my example the method won't be cloned itself. I think it should have only one copy, but here I still make this question in order to get more inputs.

  2. I remember everything in Python is an object. So in my example, are there two function instances with different parameters but only one copy of code?

like image 467
flypen Avatar asked Apr 04 '12 01:04

flypen


People also ask

How does callback function work in Python?

In Python, a callback is simply a function or a method passed to LocalSolver. A callback takes two parameters: the LocalSolver object that triggers the event and the type of the callback. It is possible to use the same callback method or object for multiple events or multiple LocalSolver instances.

How does callback function work?

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action. The above example is a synchronous callback, as it is executed immediately.

What's the difference between callback and function?

The main difference between a normal function and a callback function can be summarized as follows: A normal function is called directly, while a callback function is initially only defined. The function is only called and executed once a specific event has occurred.

What does __ call __ do in Python?

The __call__ method enables Python programmers to write classes where the instances behave like functions and can be called like a function. When the instance is called as a function; if this method is defined, x(arg1, arg2, ...) is a shorthand for x.


2 Answers

In Python, the callback is not simply a reference to a member function. Instead, it is "bound" to the object that it refers to when it was created. So a.func creates a callable that is bound to a, and b.func creates a callable that is bound to b.

Python only needs one implementation of func() in memory, but it will probably create one or more "trampoline" functions at runtime to accomplish the binding (I'm not certain of the internal details on this, and it would differ between Python implementations anyway).

If you print id(callback_a) and id(callback_b) you will get different results, showing that they are indeed different callable objects.

like image 122
Greg Hewgill Avatar answered Sep 23 '22 07:09

Greg Hewgill


Specific to CPython, there is only one copy of the function object. During instance creation, the class wraps the unbound functions in its namespace as bound methods. But they all wrap the same function.

Here's your example expanded to show what's going on.

class A(object):   def __init__(self, flag):     self.flag = flag    def func(self):     print self.flag  a = A(1) b = A(2)  callback_a = a.func callback_b = b.func  print "typeof(callback_a) = {0}".format(type(callback_a)) print "typeof(callback_b) = {0}".format(type(callback_b))  print "typeof(callback_a.__func__) = {0}".format(type(callback_a.__func__)) print "typeof(callback_b.__func__) = {0}".format(type(callback_b.__func__))  print "'callback_a.__func__ is callback_b.__func__'  is {0}".format(callback_a.__func__ is callback_b.__func__)  callback_a() callback_b() 

This code outputs

typeof(callback_a) = <type 'instancemethod'> typeof(callback_b) = <type 'instancemethod'> typeof(callback_a.__func__) = <type 'function'> typeof(callback_b.__func__) = <type 'function'> 'callback_a.__func__ is callback_b.__func__'  is True 

You can clearly see, using the is operator, that both instancemethod classes are sharing the same function object.

like image 42
aaronasterling Avatar answered Sep 22 '22 07:09

aaronasterling