Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

types.MethodType third argument in python2

I have inherited code that looks something like this:

class A:
  def __init__(self):
    print('A')

def foo(self, *args):
  print('foo')

a = A()
setattr(a,'foo',types.MethodType(foo,a,A))

For that last line, I want to make the code 2to3 compatible, but MethodType only takes two arguments in python3.

Simplest option is probably to let it break intelligently and

try:
  setattr(a,'foo',types.MethodType(foo,a,A))
except TypeError:
  setattr(a,'foo',types.MethodType(foo,a))

But then I realized that I don't understand why I'm adding the third argument in python2, because setattr(a,'foo',types.MethodType(foo,a)) works across languages.

In Python2, what is the third argument buying me, to bind it to the class vs not?

>>> types.MethodType(foo,a)
<bound method ?.foo of <__main__.A instance at 0x1>>
>>> types.MethodType(foo,a,A)
<bound method A.foo of <__main__.A instance at 0x1>>
like image 493
pettus Avatar asked Feb 18 '18 23:02

pettus


1 Answers

In Python 2, the third argument to the method type constructor was mostly used for unbound method objects:

>>> class Foo(object):
...     def bar(self):
...         pass
...
>>> Foo.bar
<unbound method Foo.bar>

A direct constructor call to create one of these would have looked like types.MethodType(bar, None, Foo), where bar is the function. Unbound method objects did a bit of type checking to ensure they weren't used for objects of the wrong type, but they were deemed not useful enough to justify their existence, so they got taken out in Python 3. With no more unbound method objects, there wasn't much reason for the method constructor to take a third argument, so that was removed too.

like image 170
user2357112 supports Monica Avatar answered Oct 24 '22 05:10

user2357112 supports Monica