As much as I find writing Python boring I often have to admit it is pretty well thought out. Even things that used to annoy me to no end when I first got into Python straight from the cosy Ruby world turn out to make a lot of sense in practice. Take the seemingly half-assed approach to objects and the necessity to use the self parameter in every method declaration inside Python classes. What a waste of space, right? And yet it turns out that it can make your code really expressive.

For example this:

greeting = 'hello'
greeting.upper()

…can be rewritten as this:

greeting = 'hello'
str.upper(greeting)

That’s because every ‘method’ in Python is in fact a function which takes an instance as it’s first parameter. In most situations this is irrelevant and only results in us having to put that annoying first parameter in every instance method in our Python classes. But where it really shines is with inheritance chains. Let’s assume we have the following hierarchy:

class Animal(object):
  def say(self):
    return '[awkward silence]'

class Human(Animal):
  def say(self):
    return 'I am hungry'

class Baby(Human):
  def say(self):
    return 'aaaaaaa! aaaaaa!! aaaaaaa!!!'

Now let’s assume the worst - we’re left with a crying Baby.

>>> b = Baby()
>>> b.say()
'aaaaaaa! aaaaaa!! aaaaaaa!!!'

Turns out that with a bit of effort we can use the power that comes from the abovementioned annoyance to make our Baby a really quiet, generic Animal:

>>> b = Baby()
>>> Animal.say(b)
'[awkward silence]'

See what we’ve done there? And this is even sorta kinda type-safe! Let’s assume we have an object that implements the same method but is not related to our Baby object. Like, an Extraterrestrial:

class Extraterrestrial(object):
  def say(self):
    return 'We come in peace'

Even though Python is generally color-blind when it comes to type safety, it does something surprisingly clever here:

>>> b = Baby()
>>> Extraterrestrial.say(b)
TypeError: unbound method say() must be called with Extraterrestrial instance as
first argument (got Baby instance instead)

Kaboom. So you can’t really have your Baby come in peace. Oops.

If you’re still here you might be wondering if ye olde Ruby can pull the same trick. Of course it can - the syntax may feel a bit awkward at first but the concept (unbound methods) is the same. Let’s translate our object hierarchy into Ruby:

class Animal
  def say; '[awkward silence]'; end
end

class Human < Animal
  def say; 'I am hungry'; end
end

class Baby < Human
  def say; 'aaaaaaa! aaaaaa!! aaaaaaa!!!'; end
end

So how do I keep my Baby quiet in Ruby?

b = Baby.new
 => #<Baby:0x007febec9e9320>
b.say
 => "aaaaaaa! aaaaaa!! aaaaaaa!!!"
Animal.instance_method(:say).bind(b).call
 => "[awkward silence]"

Let’s follow step by step what happened here:

b = Baby.new
 => #<Baby:0x007febec980078>
method = Animal.instance_method(:say)
 => #<UnboundMethod: Animal#say>
fn = method.bind(b)
 => #<Method: Baby(Animal)#say>
fn.call
 => "[awkward silence]"

So there it is. I’ve created an instance of UnboundMethod, then bound an instance of Baby to it which resulted in a Method which in turn presents the same calling interface as a Proc. The reason I could do it is the same as in Python - since Baby is still a valid Animal there is no reason why I should not be able to run Animal’s methods on it, even if they were overridden in the inheritance chain. An attempt for a Baby to behave like an Extraterrestrial will fail here as well:

class Extraterrestrial
  def say; 'We come in peace'; end
end
b = Baby.new
Extraterrestrial.instance_method(:say).bind(b)
=> TypeError: bind argument must be an instance of Extraterrestrial

That’s it for today, happy binding!