Overwritten methods do not contain self?

Here is an example that I just reproduced on my machine:

$ python Python 2.7.4 (default, Apr 19 2013, 18:28:01) [GCC 4.7.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. # just a test class >>> class A(object): ... def hi(self): ... print("hi") ... >>> a = A() >>> a.hi() hi >>> def hello(self): ... print("hello") ... >>> >>> hello(None) hello >>> >>> >>> >>> a.hi = hello # now I would expect for hi to work the same way as before # and it just prints hello instead of hi. >>> a.hi() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: hello() takes exactly 1 argument (0 given) >>> >>> def hello(): ... print("hello") ... # but instead this one works, which doesn't contain any # reference to self >>> a.hi = hello >>> a.hi() hello >>> >>> >>> >>> >>> a.hello = hello >>> a.hello() hello 

What's going on here? Why does the function not receive the self parameter when it is used as a method? What do I need to do to get a link to myself inside?

+4
source share
2 answers

The method in the class referenced through the instance is bound to that instance, in your case:

 In [3]: a.hi Out[3]: <bound method A.hi of <__main__.A object at 0x218ab10>> 

Compare with:

 In [4]: A.hi Out[4]: <unbound method A.hi> 

So, to achieve the effect that you probably want, do

 In [5]: def hello(self): ...: print "hello" ...: In [6]: A.hi = hello In [7]: a.hi() hello 

Beware - this applies to all instances of A But if you want to override the method for only one instance, do you really need to pass self ?

+8
source

This is a way to access functions when they are class attributes.

A function added as an attribute of a class is accessed as a descriptor . You see, if you do

 class A(object): pass def f(*a): pass Af = f print f print Af print A().f 

Here you get the conclusion

 <function f at 0x00F03D70> <unbound method Af> <bound method Af of <__main__.A object at 0x00F089D0>> 

You get the same thing with

 print f print f.__get__(None, A) print f.__get__(A(), A) 

because this is the way descriptors work.

All this β€” the conversion from function to method through the handle protocol β€” does not occur in instance attributes.

If you do

 a = A() af = f 

then af also read as a function, not as a method. Therefore, you should take this into account during the course of the assignment and, rather, do

 af = lambda: f(a) 

to pass a function.

+3
source

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


All Articles