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

Cameron Simpson cs at cskk.id.au
Tue Aug 8 02:59:07 EDT 2017


On 07Aug2017 20:22, boB Stepp <robertvstepp at gmail.com> wrote:
>On Mon, Aug 7, 2017 at 8:36 AM, Steven D'Aprano <steve at pearwood.info> wrote:
[...]
>> It is hard to see the distinction between an ordinary method and a
>> static method from this example. What you are seeing is, by accident,
>> the equivalent of just writing:
>>
>> def my_method():
>>     print('This is my_method in MyClass!')
>>
>> outside of the class and calling the bare function. Notice that despite
>> the name, my_method is not *actually* usable as a method. It has no
>> "self" parameter.
>
>I thought that was the whole essence of static methods -- no self parameter.

The point of a static method is that it doesn't have an instance or class 
context (a method's first argument).

A method gets called like this:

  obj.method(blah)

where obj is an instance of the class and blah is some arguments.

A method can be defined, essentially, 3 ways:

  def method(self, blah):

  @classmethod
  def method(klass, blah):

  @staticmethod
  def method(blah):

They all can be _called_ the same way. The decorator controls what context they 
receive. An ordinary method gets the instance ("obj", above) as its first 
argument as context. A class method receives the instance's class as its first 
argument as context. A static method gets no context, and no presupplied 
parameter.

What Steven is getting at is that if you define a method like this:

  def my_method():

is is supposed to be an ordinary method. However, orderinary methods are handed 
the instance ("obj") as the first parameter, and you have specified no 
parameter. This will blow up when you call it:

  class K(object):
    def m():
      pass

  o=K()
  o.m()
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  TypeError: m() takes 0 positional arguments but 1 was given

This is because m() is an ordinary method, and therefore it gets called with 
"o" as the first parameter. But it doesn't expect that, hence the TypeError.

Now, you _can_ call m() via the class:

  K.m()

but the point of classmethods and staticmethods is that you can call them on 
instances, and the caller doesn't need to know what style of method they are.  
The caller just goes:

  K.m(blah)

and doesn't care.

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


More information about the Tutor mailing list