Until like one hour ago, I was convinced that in python Foo ().bar () was nothing more than a short hand for Foo.bar (Foo () ) which passes the instance as first parameter. In this example the last two lines do (apparently) the same thing:
class Foo (object):
def bar (self): print "baz"
qux = Foo ()
qux.bar ()
Foo.bar (qux)
But now I have a class Animal that has a static method populate() that returns a list of all animals known to man. Also each instance of Animal has a method populate() that fills the properties of the instance with random values.
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import random
animals = [ ("Bella", "cow"), ("Spike", "dog"), ("José", "iguana"), ("Tux", "penguin") ]
class Animal (object):
@staticmethod
def populate (*args): return map (lambda x: Animal (*x), animals)
def __init__ (self, name = None, species = None):
def bar (): self.name, self.species = random.choice (animals)
self.name = name
self.species = species
self.populate = bar
def __repr__ (self): return "%s of species %s" % (self.name, self.species)
print Animal.populate ()
print Animal ("Pinky", "mouse")
qux = Animal ()
qux.populate ()
print qux
The code works fine, but what made me suspicious was the fact that print Animal.populate (qux) called the static populate method (and hence returned a list and did not populate poor qux). So apparently my conviction that Foo ().bar () was nothing more than a short hand for Foo.bar (Foo () ) is wrong.
This raises various questions for me:
- What happens when I call
Foo ().bar ()? - What happens when I call
Foo.bar (Foo () )? - Is there an internal difference between the both?
- Am I missing some fundamental concept of python?
- If you had to write a class whose static populate method does something else than the populate method invoked over an instance of this class, which would be the way to go?
(Yes it must be the same name.)
On the difference between Foo().bar(), Foo.bar(Foo()) and Foo.bar() (as an answer because I signed up yesterday and can’t post comments yet) – this is because of Python(<3.0)’s concept of ‘bound’ and ‘unbound’ methods – it strictly requires that, except with @staticmethod or @classmethod, method calls have an instance associated with them. There’s not really any easier way to explain it than just something you have to remember.
Thankfully, this has changed in Python 3 – the concept of ‘bound’ and ‘unbound’ methods as separate things has gone, and Foo.bar() works just fine for your example.