types.MethodType third argument in python2 - python

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

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.

A python2 / python3 compatible way to accomplish what you want is to use the descriptor protocol (__get__):
class A(object):
def __init__(self):
print('A')
def foo(self, *args):
print('foo')
a = A()
setattr(a,'foo', foo.__get__(a, A))
.__get__ will return a bound method instance

Related

Different ways of calling methods in Python, How they work?

class Test():
def a(self):
return 6
Test_instance=Test()
print(Test.a(Test_instance))
print(Test_instance.a())
print(Test.a(Test_instance,3))
print(Test_instance.a(3))
The code above give me the following result:
6
6
TypeError: a() takes 1 positional argument but 2 were given
If I exclude the line print(Test.a(Test_instance,3)) I get the same print out. But Isn't a a method of both, Test class and Test_instance object? When I write Test_instance.a() I supose I'm giving one argument to the a() method of Test_instance and when I write Test.a(Test_instance) I supose I'm giving two arguments to the a() method of Test. But the error says that Test.a(Test_instance,3) gives 2 arguments. Shouldn't it be 3?
But Isn't "a" a method of both, Test object and Test_instance object?.
It is indeed.
When I write Test_instance.a() I supose im giving one argument to "a" method of Test_instance and When I write Test.a(Test_instance) I supose Im giving two arguments to "a" method of Test.
Right. But that applies only to method calls on instances.
But the error says that Test.a(Test_instance,3) gives 2 arguments. Shouldn't be 3?
No. It is 2, as you call the method directly on the class and not via the instance.
Calling a method directly on the class calls it as it is.
Calling a method on the instance, however, prepends the instance as first argument.
The reason for this are the internals.
If I do instance.X, X is a class member and implements the __get__() method (Descriptor protocol), internally X.__get__() is called and the result of it is produced for instance.X.
And functions implement the descriptor protocol in order to create an instance method object, which is reponsible for prepending the instance as first argument.
So, in your example, you as well can do
>>> print(Test_instance.a)
<bound method Test.a of <__main__.Test instance at 0x7f6e232e3690>>
>>> Test.a.__get__(Test_instance, Test)
<bound method Test.a of <__main__.Test instance at 0x7f6e232e3690>>
Both these "bound methods" are what I referred to as "instance method object".
Other example for this:
class Desc(object):
def __get__(self, a, b):
print('Calling __get__(%r, %r, %r)' % (self, a, b))
return a or b
class Test():
x = Desc()
>>> Test.x
Calling __get__(<__main__.Desc object at 0x7f6e232e1810>, None, <class __main__.Test at 0x7f6e232ea050>)
<class __main__.Test at 0x7f6e232ea050>
>>> inst = Test()
>>> inst.x
Calling __get__(<__main__.Desc object at 0x7f6e232e1810>, <__main__.Test instance at 0x7f6e232e3c80>, <class __main__.Test at 0x7f6e232ea050>)
<__main__.Test instance at 0x7f6e232e3c80>
What happens here?
Test.x takes the x member of Test and calls its .__get__(x, None, Test). This method returns b (which is set to Test), as the a parameter is None.
inst.x takes the x member of Test and calls its .__get__(x, inst, Test). This in turn returns a.
In a similar way, methods are set up to work.
Properties as well use the same mechanism, BTW.
If you use the #classmethod and #staticmethod decorators, they wrap the functions into some wrapping objects which have a slightly different .__get__() behaviour.
When you do instance.a(), instance is impliciltly passed as the first argument. When you do instance.a(3), you give two arguments (the implicit first instance, and the explicit 3), which your function cannot handle.
When you do Test.a(), Test is not passed as an implicit first argument because a is not defined as a class method.
If you do
class Test():
#classmethod
def a(self):
return 6
and then try Test.a(123) would give you the error a() takes 1 positional argument but 2 were given
Or Test.a(Test_instance,3), you'll get the error you expect.

Can I pass self as the first argument for class methods in python

I am trying to understand the class methods. From what I have read it looks like for the class methods we have to pass cls as the first argument while defining (Similar to instance methods where we pass the self as the first argument). But I see that even if I pass the self as the first argument for a class method it works. Can someone explain me how this works?
I have seen some usage where they have defined the class as a class method but they still pass self as the first argument instead of cls. I am trying to understand the usage.
#!/usr/bin/python
class A(object):
def foo(self,x):
print "executing foo(%s,%s)"%(self,x)
#classmethod
def class_foo(self,x):
print "executing class_foo(%s,%s)"%(self,x)
>>> A.class_foo(2)
executing class_foo(<class '__main__.A'>,2)
>>>
The use of self and cls is just a naming convention. You can call them whatever you want (don't though!). As such you're still passing in the class object, you've just named it self, rather than cls.
99.999% of Python programmers will expect you to call them self and cls, also a lot of IDEs will complain if you call them anything but self and cls, so please stick to the convention.
i feel like the last answer only discusses the naming convention of the first parameter without explaining what self evaluates to for what is known as a static method vs a regular method. take the following example:
class A(object):
def x(self):
print(self)
#classmethod
def y(self):
print(self)
a = A()
b = A()
c = A()
print(a.x())
print(b.x())
print(c.x())
print()
print(a.y())
print(b.y())
print(c.y())
the output is the following:
<__main__.A object at 0x7fc95c4549d0>
None
<__main__.A object at 0x7fc95c454a10>
None
<__main__.A object at 0x7fc95c454a50>
None
()
<class '__main__.A'>
None
<class '__main__.A'>
None
<class '__main__.A'>
None
notice that the method x called by the 3 objects yields varying hex addresses, meaning that the self object is tied to the instance. the y method shows that self is actually referencing the class itself rather than the instance. that is the difference.

Why don't Python class method decorators receive the method as a bound method?

When I create a decorator for a class method, it always receives the method as of type "function".
However, when I play around with things a bit, I only get back bound methods:
class Test(object):
def save(self):
print "Save called"
def func(self):
print "Func called"
And then:
>>> type(Test.func)
<type 'instancemethod'>
>>> type(Test().func)
<type 'instancemethod'>
What I would ultimately like to do is create a class method decorator, which also decorates some other method on the same class. How would I go about doing this?
This is impossible; you'd have to use a class decorator or metaclass instead. Decorator syntax
class Foo(object):
#dec
def bar(self): pass
means
class Foo(object)
def bar(self): pass
bar = dec(bar)
where a class definition is processed as: execute the body, then gather the definitions and wrap them in a class object. I.e., decoration is done before the class comes into existence.
It depens on the order of stuff that happens.
If you take a "normal" method. the following happens:
class Test(object):
def save(self):
print "Save called"
def func(self):
print "Func called"
>>> Test.__dict__["func"]
<function func at 0x00B43E30>
>>> Test.func
<unbound method Test.func>
Should be the same. What happens here? Well, look:
>>> f = Test.__dict__["func"]
>>> m = f.__get__(None, Test)
>>> f, m
(<function func at 0x00B43E30>, <unbound method Test.func>)
The first is the original function object, the second one the method object which is created when doing an actual method call.
Furthermore, if you have an instance:
>>> t = Test()
>>> t.func
<bound method Test.func of <__main__.Test object at 0x00B48AB0>>
>>> f.__get__(t, Test)
<bound method Test.func of <__main__.Test object at 0x00B48AB0>>
So this happens on attribute access.
Now to your question:
The reason this happens is because the original function is present in the class's __dict__. The method object creation happens on access.

Are there any benefits from using a #staticmethod?

I was wondering if you use #staticmethod decorator in your code.
Personally I don't use it, since it takes more letters to write #staticmethod then self.
The only benefit (which comes to me) from using it may be a better clarity of a code, but since I usually write a method description for sphinx, I always state whether a method is using object or not.
Or maybe I should start using #staticmethod decorator ?
Whether to use #staticmethod or not depends on what you want to achieve. Ignoring the decorator because there is more to type is a rather silly reason (no offense!) and indicates that you have not understood the concept of a static method in Python!
Static methods are independent of the class and any class instance. They only use the class scope as a namespace. If you omit the #staticmethod decorator, you are creating an instance method that cannot be used without constructing an instance.
Here is a very simple class Foo:
>>> class Foo(object):
... #staticmethod
... def foo():
... print 'foo'
...
... def bar(self):
... print 'bar'
Now, Foo.foo() is a static method that can be called directly:
>>> Foo.foo()
foo
Foo.bar() on the other hand is an instance method, that can only be called from instances (objects) of Foo:
>>> Foo.bar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with Foo instance as first argument (got nothing instead)
>>> foo = Foo()
>>> foo.bar()
bar
To answer your question: If you want to define a static method, use #staticmethod. Otherwise, don't.
If you have a method that does not use self, and therefore could be written as a static method, ask yourself: Will you ever want to access this function from outside without having an instance? Most of the times, the answer will be: No.
Assume that we want to define abs method in class Math, then we have two choices:
class Math():
def abs(n):
if n>0:
return n
else:
return -n
class Math2():
#staticmethod
def abs(n):
if n>0:
return n
else:
return -n
In Python2:
>>> Math.abs(-2)
TypeError: unbound method abs() must be called with Math instance as
first argument (got int instance instead)
>>>Math().abs(-2)
TypeError: abs() takes exactly 1 argument (2 given)
>>> Math2.abs(-2)
2
>>> Math2().abs(-2)
2
python2 automatically takes Math().abs(-2) as Math().abs(self,-2),so that you have to use #staticmethod.
In Python3
>>>Math.abs(-3)
3
>>>Math().abs(-3)
TypeError: abs() takes 1 positional argument but 2 were given
>>>Math2.abs(-3)
3
>>>Math2().abs(-3)
3
In python3, you can use classname.method() without static method, but it will raise TypeError when someone tries to use instance.method().
#staticmethod decorator saves you typing and improves readability.
class Example:
#staticmethod
def some_method():
return
is the same as:
class Example:
def some_method():
return
some_method = staticmethod(some_method)
I think you may be confused about what a static method is in Python as the terminology differs from other languages. A regular method is "bound" to the instance (self), a class method is "bound" to the class (cls) while a static method is not "bound" at all (and can not access instance nor class attributes.
See:
http://docs.python.org/library/functions.html#classmethod
http://docs.python.org/library/functions.html#staticmethod
In addition to the previous answers,
from pythons doc #staticmethod :
It can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class.
class Test:
#staticmethod
def Foo():
print('static Foo')
def Bar():
print('static Bar')
Test.foo() # static Foo
Test.bar() # static Bar
obj = Test()
obj.foo() # static Foo ; note that you can call it from class instance
obj.bar() # ERROR

Explanation of a decorator class in python

While reading up about some python module I encountered this decorator class:
# this decorator lets me use methods as both static and instance methods
class omnimethod(object):
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
return functools.partial(self.func, instance)
What I know about decorators, is that the can extend functionality (e.g. for a function). Could someone be so kind and explain to me why the class above is useful and how it exactly works?
It is used in the code this way:
#omnimethod:
def some_function(...):
pass
Another question:
I encountered this piece of code in the same file:
#property
def some_other_function(...):
pass
#property is not defined anywhere in the file. Is this some standard decorator? If yes, what does it do? Google couldn't help me on this case.
By the way, here is the source where I found the code: http://code.xster.net/pygeocoder/src/c9460febdbd1/pygeocoder.py
that omnimethod is very clever. It uses some very subtle tricks to do it's job. Let's start at the beginning.
You probably already know that decorator syntax is just sugar for function application, ie:
#somedecorator
def somefunc(...):
pass
# is the same thing as
def somefunc(...):
pass
somefunc = somedecorator(somefunc)
so somefunc is actually an omnimethod instance, not the function that had been defined. what's interesting about this is that omnimethod also implements the descriptor interface. If a class attribute defines a __get__ method, then whenever that attribute is mentioned, the interpreter instead calls __get__ on that object, and returns that instead of returning the attribute itself.
the __get__ method is always called with instance as first argument, and the class of that instance as second argument. If the attribute was actually looked up from the class itself, then instance will be None.
The last bit of trickery is functools.partial, which is the python way of function currying. when you use partial, you pass it a function and some arguments, and it returns a new function, that when called, will call the original function with the original arguments in addition to whichever arguments you passed in later. omnimethod uses this technique to populate the self parameter to the function it wraps.
Here's what that looks like. a regular method can be called when you read it from an instance but you can't use it from the class itself. you get an unbound TypeError
>>> class Foo(object):
... def bar(self, baz):
... print self, baz
...
>>> f = Foo()
>>> f.bar('apples')
<__main__.Foo object at 0x7fe81ab52f90> apples
>>> Foo.bar('quux')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with
Foo instance as first argument (got str instance instead)
>>> Foo.bar(None, 'quux')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with
Foo instance as first argument (got NoneType instance instead)
>>>
Python provides a bultin decorator classmethod (and also staticmethod, but nevermind that), that will allow you to use it at the class level, but it never gets to see the instance. it always recieves the class as it's first argument.
>>> class Foo(object):
... #classmethod
... def bar(cls, baz):
... print cls, baz
...
>>> f = Foo()
>>> Foo.bar('abc')
<class '__main__.Foo'> abc
>>> f.bar('def')
<class '__main__.Foo'> def
>>>
By it's bit of cleverness, omnimethod gives you a little bit of both.
>>> class Foo(object):
... #omnimethod
... def bar(self, baz):
... print self, baz
...
>>> f = Foo()
>>> Foo.bar('bananas')
None bananas
>>> f.bar('apples')
<__main__.Foo object at 0x7fe81ab52f90> apples
>>>
omnimethod does what it says in the comment; it will let you call some_function as either a 'static function' on a class or as a function on an instance of the class. #property is a standard decorator (see the python docs) that exposes a function in a way that makes it look like a simple instance variable.
class B:
#omnimethod
def test(self):
print 1
#property
def prop(self):
return 2
>>> b = B()
>>> b.test()
1
>>> B.test()
1
>>> b.prop
2

Categories

Resources