Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python method lookup, static vs. instance

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:

  1. What happens when I call Foo ().bar ()?
  2. What happens when I call Foo.bar (Foo () )?
  3. Is there an internal difference between the both?
  4. Am I missing some fundamental concept of python?
  5. 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.)

like image 402
Hyperboreus Avatar asked Jun 01 '11 20:06

Hyperboreus


People also ask

What is the difference between static method and instance method in Python?

The instance method acts on an object's attributes. It can modify the object state by changing the value of instance variables. Static methods have limited use because they don't have access to the attributes of an object (instance variables) and class attributes (class variables).

What is the difference between instance method class method and static method?

Instance methods need a class instance and can access the instance through self . Class methods don't need a class instance. They can't access the instance ( self ) but they have access to the class itself via cls . Static methods don't have access to cls or self .

When should a method be static Python?

2. Having a single implementation. Static methods are used when we don't want subclasses of a class change/override a specific implementation of a method.


2 Answers

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.

like image 81
lvc Avatar answered Oct 03 '22 16:10

lvc


Static methods and class methods are special descriptors. Since the descriptor's __get__() method's arguments include both the class and any relevant instance, they can screw with the arguments to the method in any way they like.

like image 23
Ignacio Vazquez-Abrams Avatar answered Oct 03 '22 16:10

Ignacio Vazquez-Abrams