16

According to http://docs.python.org/2/library/functions.html#super,

If the second argument is omitted, the super object returned is unbound.

Which is super(type).

I am wondering what is unbounded and when is it bounded.

1
  • 11
    Both of the current answers are completely wrong. This is understandable, since it's a tricky subject. The best explanation I have found for unbound super objects is this article by Michele Simionato. That's actually just part 2 of a 3-part series. Parts 1 and 3 are very good too, if you want to understand super(). Commented Nov 7, 2014 at 21:20

5 Answers 5

5

Other answers (answer, answer) for your question already explained the meaning of the words bound / unbound.

So my focus is to explain only the use of an unbound proxy object returned from the super() function (i.e. in the case it was used only with 1 argument).

The reason for obtaining an unbound object is to bind it later.

Particularly, for the unbound object returned from the super() function you may bind it to an appropriate object using its __get__() method, e.g.

super(C).__get__(c)        # where C is a class and c is an object

To illustrate it, let's create 3 dependent classes and 3 objects - one for every class:

class A:
    def __init__(self, name):
        self.name = name
    def message(self, source):
        print(f"From: {source}, class: A, object: {self.name}")

class B(A):
    def __init__(self, name):
        self.name = name
    def message(self, source):
        print(f"From: {source}, class: B, object: {self.name}")

class C(B):
    def __init__(self, name):
        self.name = name
    def message(self, source):
        print(f"From: {source}, class: C, object: {self.name}")

a = A("a")
b = B("b")
c = C("c")

Now in the interactive console, at first for understanding things:

>>> super(B)                  # unbounded (note 'None')
<super: __main__.B, None>

>>> super(B).__get__(b)       # bounded to object b (note address)
<super: __main__.B, <__main__.B at 0xa9bdac0>>

>>> b                         # note: the same address
'<__main__.B at 0xa9bdac0>

then — to show results of using different combinations of classes / objects
(in our case for delegating the method .message()):

>>> super(B).__get__(b).message("super(B)")
From: super(B), class: A, object: b

>>> super(C).__get__(c).message("super(C)")
From: super(C), class: B, object: c

>>> super(B).__get__(c).message("super(B)")
From: super(B), class: A, object: c

and finally examples for binding and unbound proxy to appropriate classes:

>>> A.name = "Class A"            # Preparing for it - 
>>> B.name = "Class B"            # creating some class attributes

>>> super(B).__get__(B).name      # Proxy super(B) bounded to class B
'Class A'

>>> super(B).__get__(C).name      # Proxy super(B) bounded to class C
'Class A'

>>> super(C).__get__(C).name      # Proxy super(C) bounded to class C
'Class B'
Sign up to request clarification or add additional context in comments.

Comments

2

To explain terms bound / unbound I will use functions, and — to be brief — I give up details and caveats.

There are 2 views:


  1. From the user point of view there are 3 sorts of functions:
    1. Free function (unbound), for example the built-in function sum():

      sum([1, 2, 3])          # 6
      
    2. A function bound to an object (other name: object method) means that a user have to bind it to a particular object with the dot (.) notation.

      For example the use of built-in .upper() method:

      "Alice".upper()     # ALICE
      "Jacob".upper()     # JACOB (the same method; different object, different result)
      
    3. A function bound to a class (other name: class method) means that a user have to bind it to a particular class — again with the same dot (.) notation.

      Examples:

      A.some_class_method()               # A is a class
      B.some_class_method(parameters)     # B is a class
      

  1. From the designer point of view there are the same 3 sorts of functions, so I use the same numbers for them:

    1. A free (unbound) function is defined out of a class:

      def free_function(parameters):
          ...
      
    2. A function bound to an object is defined inside a class, with the first parameter reserved for an object and named self (this name is only a convention, but a very strong one):

      class A:
          def bound_to_object(self, other_parameters):
              ...
      
    3. A function bound to a class is defined inside a class, with the first parameter reserved for a class and named cls (this name is only a convention, too, but a very strong one) and with the @classmethod decorator just before it:

      class A:
          @classmethod
          def bound_to_class(cls, other_parameters):
              ...
      

Comments

0

Edit: in the context of super, much of below is wrong. See the comment by John Y.

super(Foo, a).bar returns the method called bar from the next object in the method resolution order (the MRO), in this case bound to the object a, an instance of Foo. If a was left out, then the returned method would be unbound. Methods are just objects, but they can be bound or unbound.

An unbound method is a method that is not tied to an instance of a class. It doesn't receive the instance of the class as the implicit first argument.

You can still call unbound methods, but you need to pass an instance of the class explicitly as the first argument.

The following gives an example of a bound and an unbound method and how to use them.

In [1]: class Foo(object):
   ...:     def bar(self):
   ...:         print self
   ...:         

In [2]: Foo.bar
Out[2]: <unbound method Foo.bar>

In [3]: a = Foo()

In [4]: a.bar
Out[4]: <bound method Foo.bar of <__main__.Foo object at 0x4433110>>

In [5]: a.bar()
<__main__.Foo object at 0x4433110>

In [6]: Foo.bar()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-bb3335dac614> in <module>()
----> 1 Foo.bar()

TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)

In [7]: Foo.bar(a)
<__main__.Foo object at 0x4433110>

2 Comments

This answer is not a bad description of bound versus unbound methods, but it is completely incorrect regarding super(). An unbound super object (which is returned by calling super() with only one argument) cannot even access the methods you are trying to call. Try it and see. You will get AttributeError: 'super' object has no attribute 'bar'. Check this out for more info.
Well I'll be buggered. Thanks for that!
0

There are several things covered in other answers, but there is a missing link that ties all of them together. An explanation of (un)bounded methods are given and examples of how the unbounded super object can be used, but these don't really explain what the relationship between them are and how the unbounded super object should be used.

The key is realizing that unbounded objects merely refers to descriptors, which are similar to properties. A descriptor is a class variable which has getter, setter, and/or deleter methods. These methods are then invoked when used in the appropriate way by instances.

So, how can we actually use these descriptors in this case? Well it turns out all we need to do is bind it to a class, like this:

class A:
    def foo(self):
        print("A")


class B(A):
    def foo(self):
        print("B")


B.parent = super(B)

Setting B.parent to a descriptor is the same as doing this:

class B(A):
    pass


def foo(self):
    print("B")

B.foo = foo

We can then apply this functionality to our instances:

x = B()
x.foo()  # B
x.parent.foo()  # A

which demonstrates how to use them. What actually happens in this case is that foo and parent are both descriptors. When binding foo to x, it fills the first argument with x and returns the resulting method. When binding parent to x, it does the same thing, filling in the next argument of super. This means using x.parent is equivalent to using super(B, x), which is what using super() inside of a method becomes.

Comments

-4

"Unbound" means it will return the class, rather than an instance of the class.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.