[Tutor] Difference(s) betweenPython 3 static methods with and without @staticmethod?

Cameron Simpson cs at cskk.id.au
Tue Aug 8 05:14:22 EDT 2017


On 08Aug2017 08:39, Alan Gauld <alan.gauld at yahoo.co.uk> wrote:
>>> (1) There are very, very few good uses for static methods in Python. If
>>> you think you need a static method, you probably could just use a
>>> regular module-level function.
>
>Amen to that, I try to avoid staticmethods... and so far
>have never found a valid use for one. I treat them as a
>piece of legacy from earlier versions, prior to classmethods.

I use them a bit for things that _could_ be module level functions, but using a 
static method lets me (a) associate if with a class and (b) one gets access to 
the method when one imports the class. So one can write code like this:

  from my_module import SomeDataFormat

  with open(datafile) as f:
    header_info = SomeDataFormat.parse_header(f)

and the module's SomeDataFormat class might have:

  class Foo:

    @staticmethod
    def parse_header(f):
      # decode the header structure and return info about it

That could easily be a standalone module function, but if the header record is 
a specific to the class then one can expose the parser function as a static 
method: it comes in with the class when it is imported, and it is clear that 
the parser is for what the class manages. It lets you avoid 
cumber_long_function_names because the "SomeDataFormat." contributes to the 
description.

I've also used them for factories, but think a class method is better. Thus:

  class Foo:

    def __init__(self, x, y, z):
      self.x = x
      self.y = y
      self.z = z

    @staticmethod
    def from_point(p):
      return Foo(p.x, p.y, p.z)

so that one can make a Foo directly:

  f = Foo(1,2,3)

or from some hypothetical "point" object:

  f = Foo.from_point(p)

But arguably this would be better as a class method anyway:

  @classmethod
  def from_point(klass, p):
    return klass(p.x, p.y, p.z)

because it lets you subclass Foo:

  class Bah(Foo):

and call Bah.from_point(p) for free, and it will make a Bah instead of a Foo 
because it gets the class as "klass".

Cheers,
Cameron Simpson <cs at cskk.id.au> (formerly cs at zip.com.au)


More information about the Tutor mailing list