How does monkeypatch have one class instance method for another?

Given class A , I can simply add the instance method A via

 def a(self): pass Aa = a 

However, if I try to add another class B instancemethod B , i.e. Ab = Bb , trying to call A().b() gives

TypeError : unbound method b() should be called with instance B as the first argument (nothing fails instead)

(so far B().b() excellent). Indeed, there is a difference between

 Aa -> <unbound method Aa> Ab -> <unbound method Bb> # should be Ab, not Bb 

So,

  • How to fix it?
  • Why is that? This does not seem intuitive, but usually Guido has good reasons ...

Curiously, this no longer fails in Python3 ...

+4
source share
2 answers

Let's:

 class A(object): pass class B(object): def b(self): print 'self class: ' + self.__class__.__name__ 

When you do:

 Ab = Bb 

You are not attaching a function to A, but an unrelated method. As a result, python only adds it as a standard attribute and does not convert it to an A-unlimited method. The solution is simple, attach the main function:

 Ab = Bb__func__ print Ab # print: <unbound method Ab> a = A() ab() # print: self class: A 

I don’t know the whole difference between unrelated methods and functions (only the first contains the second), nor how it all works inside. Therefore, I cannot explain the reason for this. I understand that a method object (bound or not) requires more information and functions than functions, but this requires execution.

I would agree that automating this (changing the class of an unrelated method) may be a good choice, but I can find reasons not to. It is therefore surprising that python 3 is different from python 2. I would like to know the reason for this choice.

+6
source

When you take a reference to a class instance method, the method is bound to this class instance.

B().b equivalent to: lambda *args, **kwargs: b(<B instance>, *args, **kwargs)

I suspect that you get a similar (but not identical) wrapped link when evaluating Bb. However, this is not the behavior that I expected.

Interesting:

 Aa = lambda s: Bb(s) A().a() 

gives:

TypeError: unbound method b () should be called with instance B as the first argument (received an instance instead)

This suggests that Bb evaluates the wrapper for the actual method, and the shell checks that the self is of the expected type. I do not know, but it is probably about the effectiveness of the interpreter.

This is an interesting question. I hope someone can answer a more categorical answer.

+1
source

Source: https://habr.com/ru/post/1501423/


All Articles