Wednesday, 8 January 2014

Python gotcha: bound method

A quick Python observation that will hopefully save somebody some time. Given the following Python code:

class Example:
    X = 5

    def __init__(self, value):
        self.some_value = value

    def method(self, value):
        if value > Example.X:
            return 'Yup'
        return 'Nope'

    def another_method(self):
        return self.method(self.some_value)

e = Example(2)
print e.some_value

This code defines a class named Example, instantiates it and prints out one of the class member variables. In this case the code will print out the value "2" which is logical as it was used to instantiate the object.

Extending this and trying to do:
print e.another_method

Results in output that looks something like:
<bound method Example.another_method of <__main__.Example instance at 0x7ffde0f4fd88>>

This seems a bit strange until you realise that Python is doing exactly what you are telling it to do which is return the method object rather than invoke the method. There are two really simple fixes to this:
  1. Change the call to "print e.another_method()", this causes the method to be invoked and the result returned as expected (rather obvious really)
  2. Add the @property decorator to the method definition. This allows you to access the method as a read-only property
Both approaches work but they are mutually exclusive. Changing the method definition to:

    @property
    def another_method(self):
        return self.method(self.some_value)


And then trying to call e.another_method() will result in the error:
TypeError: 'str' object is not callable