views:

237

answers:

4

I'm trying to learn myself the super() function in Python.

I though I got a grasp of it untill I came over this example (2.6) and found myself stuck.

http://www.cafepy.com/article/python_attributes_and_methods/python_attributes_and_methods.html#super-with-classmethod-example

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test.py", line 9, in do_something
    do_something = classmethod(do_something)
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
>>>

It wasn't what I expected when I read this line right before the example:

If we're using a class method, we don't have an instance to call super with. Fortunately for us, super works even with a type as the second argument. --- The type can be passed directly to super as shown below.

Which is exactly what Python tells me is not possible by saying that do_something() should be called with an instance of B.

Thanks in advance

+2  A: 

The example from the web page seems to work as published. Did you create a do_something method for the superclass as well but not make it into a classmethod? Something like this will give you that error:

>>> class A(object):
...     def do_something(cls):
...         print cls
... #   do_something = classmethod(do_something)
... 
>>> class B(A):
...     def do_something(cls):
...         super(B, cls).do_something()
...     do_something = classmethod(do_something)
... 
>>> B().do_something()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in do_something
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
Ned Deily
No, my A class looks like this:class A(object): def do_your_stuff(self): print "this is A"Is it necessary to have "class A" as you posted it?(with do_something = classmethod(do_something)) ?I feel like the document didn't tell anything about this ..
dezza
The whole point of the `super` call in the B do_something method is to call a method of that name in one of its superclasses. If there isn't one in A (or in Object), the B().do_something() call fails with `super object has no attribute do_something`. ~unutbu rightly points out that the example in the document is faulty.
Ned Deily
Thanks alot for your help :)
dezza
+2  A: 

dezza, sometimes texts have to be read more for the flavor of the idea rather than for the details. This is one of those cases.

In the linked page, Examples 2.5, 2.6 and 2.7 should all use one method, do_your_stuff. (That is, do_something should be changed to do_your_stuff.)

In addition, as Ned Deily pointed out, A.do_your_stuff has to be a class method.

class A(object):
    @classmethod
    def do_your_stuff(cls):
        print 'This is A'

class B(A):
    @classmethod
    def do_your_stuff(cls):
        super(B, cls).do_your_stuff()

B.do_your_stuff()

super(B, cls).do_your_stuff returns a bound method (see footnote 2). Since cls was passed as the second argument to super(), it is cls that gets bound to the returned method. In other words, cls gets passed as the first argument to the method do_you_stuff().

So super(B, cls).do_your_stuff() causes A's do_your_stuff method to be called with cls passed as the first argument. In order for that to work, A's do_your_stuff has to be a class method. The linked page doesn't mention that, but it's true.

PS. do_something = classmethod(do_something) is the old way of making a classmethod. The new(er) way is to use the @classmethod decorator.

unutbu
Thanks alot for your excellent explanation.
dezza
dezza, you are very welcome! :)
unutbu
A: 

I think I've understood the point now thanks to this beatiful site and lovely community.

If you don't mind please correct me if I'm wrong on classmethods (which I am now trying to understand fully):


# EXAMPLE #1
>>> class A(object):
...     def foo(cls):
...             print cls
...     foo = classmethod(foo)
... 
>>> a = A()
>>> a.foo()
# THIS IS THE CLASS ITSELF (__class__)
class '__main__.A'

# EXAMPLE #2
# SAME AS ABOVE (With new @decorator)
>>> class A(object):
...     @classmethod
...     def foo(cls):
...             print cls
... 
>>> a = A()
>>> a.foo()
class '__main__.A'

# EXAMPLE #3
>>> class B(object):
...     def foo(self):
...             print self
... 
>>> b = B()
>>> b.foo()
# THIS IS THE INSTANCE WITH ADDRESS (self)
__main__.B object at 0xb747a8ec
>>>

I hope this illustration shows ..

dezza
For an explanation of classmethods, perhaps you'll find this helpful: http://stackoverflow.com/questions/1669445/what-is-the-difference-between-a-static-method-and-class-method-in-python/1669524#1669524
unutbu
Aha. So classmethods is a way of extending an object for example dict in this case with the video by http://www.youtube.com/watch?v=E_kZDvwofHY at 00:45:00 approx. so the method becomes a part of the original definition of the class?
dezza
+1  A: 

I've updated the article to make it a bit clearer: Python Attributes and Methods # Super

Your example using classmethod above shows what a class method is - it passes the class itself instead of the instance as the first parameter. But you don't even need an instance to call the method, for e.g.:

>>> class A(object):
...     @classmethod
...     def foo(cls):
...         print cls
... 
>>> A.foo() # note this is called directly on the class
<class '__main__.A'>
Shalabh
Great ! This will sort some things out :)
dezza