Вопрос по python – Как Python различает функцию обратного вызова, которая является членом класса?

24

Пожалуйста, посмотрите на простой пример:

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()

Результат:

1
2

Это работает, как ожидалось. Но у меня есть вопрос. В C функция обратного вызова передается как указатель. В Python для этого должен быть подобный способ, чтобы вызывающая сторона знала адрес функции. Но в моем примере передается не только указатель функции, но и параметр (self), потому что один и тот же метод одного и того же класса печатает разные результаты. Итак, мои вопросы:

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.

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?

@aaronasterling: Хотя я не уверен, что это имеет слишком большое влияние на рассматриваемый вопрос? jdi
@jdi Всегда есть возможность узнать что-то новое. aaronasterling
@Darthfett. Соблюдайтеprint statements. aaronasterling
Вы должны использовать классы newstyle. Подкласс все отobject или что-то, что подклассы это. aaronasterling
Я думаю, что это создает закрытие? Aram Kocharyan

Ваш Ответ

2   ответа
15

о время создания экземпляра класс оборачивает несвязанные функции в своем пространстве имен как связанные методы. Но все они выполняют одну и ту же функцию.

Вот ваш пример, расширенный, чтобы показать, что происходит.

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()

Этот код выводит

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

Вы можете четко видеть, используяis оператор, который какinstancemethod классы совместно используют один и тот же объект функции.

callback_a is callback_bError: User Rate Limit ExceededFalseError: User Rate Limit ExceededinstancemethodError: User Rate Limit ExceededANDError: User Rate Limit Exceeded__func__Error: User Rate Limit ExceededselfError: User Rate Limit Exceeded
Error: User Rate Limit Exceededprint "'callback_a is callback_b' is {0}".format(callback_a is callback_b)Error: User Rate Limit ExceededfalseError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
19

этого он «связан» к объекту, на который он ссылается, когда он был создан. Такa.func создает вызываемый, который связан сa, а такжеb.func создает вызываемый, который связан сb.

Python нужна только одна реализацияfunc() в памяти, но он, вероятно, создаст один или несколько «батутов» функции во время выполнения, чтобы выполнить связывание (я не уверен во внутренних деталях этого, и это все равно будет отличаться между реализациями Python).

Если вы печатаетеid(callback_a) а такжеid(callback_b) вы получите разные результаты, показывающие, что это действительно разные вызываемые объекты.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededid(a.func)Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededid(b.func) == id(a.func)Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededa_func = a.func; b_func = b.func; id(a_func) == id(b_func). a.funcError: User Rate Limit Exceededb.funcError: User Rate Limit Exceededid(a.func)Error: User Rate Limit Exceededid(b.func)Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededidError: User Rate Limit Exceeded

Похожие вопросы