14

I thought that the following code would result in an error because as far as I have read, a method in a Python class must either have "self" (or any other label, but "self" by convention) as its first argument, or "cls" or similar if the @classmethod decorator is used, or none if the @staticmethod decorator is used.

How come I get no error running this with Python 3.5 in the Terminal, even though test_method does not meet these requirements? It seems to work fine as a static method, but without the decorator.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
class MyClass:
 def test_method(args):
 print(args[1])
 @staticmethod
 def static_method():
 print("static_method")
 @classmethod
 def class_method(cls):
 print("class_method")
def main(args):
 MyClass.test_method(args)
if __name__ == '__main__':
 sys.exit(main(sys.argv))

Output:

$ python3 testscript.py "testing"
$ testing

EDIT:

My question could also be phrased differently, drawing attention away from self and to @staticmethod: "How come I'm getting a seemingly working static method without the @staticmethod decorator?"

asked Oct 16, 2018 at 8:51
4
  • 6
    Short answer is: it's not a method until you create an instance of the class. It's simply a function. Try MyClass().text_method('test') and you will get an error. Commented Oct 16, 2018 at 9:13
  • @Jblasco If it is not a method but simply a function, how is it different from a static method declared with the decorator? Commented Oct 16, 2018 at 9:18
  • 1
    Perhaps this question answers , your query Commented Oct 16, 2018 at 9:24
  • 1
    A method will be accesible from an instance of the class, @Theod'Or. In other words, this cannot be used from an instance, only from the class itself. Commented Oct 16, 2018 at 9:27

4 Answers 4

16

In Python 2, functions defined in a class body are automatically converted to "unbound methods", and cannot be called directly without a staticmethod decorator. In Python 3, this concept was removed; MyClass.text_method is a simple function that lives inside the MyClass namespace, and can be called directly.

The main reason to still use staticmethod in Python 3 is if you also want to call the method on an instance. If you don't use the decorator, the method will always be passed the instance as the first parameter, causing a TypeError.

answered Oct 16, 2018 at 9:34
Sign up to request clarification or add additional context in comments.

3 Comments

I've accepted this answer because it makes the distinction between Python 2 and 3 clear. It's really what was throwing me, I did not know this change had taken place (not been using Python for a while). Thank you!
What do you mean by "can be called directly"? That I don't have to create an object of type MyClass first on which I will call text_method()?
Yes, call with MyClass.text_method(...).
6

There is nothing special about this. In python 3 there is no difference between a function defined inside a class or a function defined outside a class. Both of them are normal functions.

The self that you are talking about here or maybe cls comes into picture only when you access the function through an instance. Hence here you didn't get any error.

However if you modify your code just a little bit to look like the following, then you'd get an error that you expected.

def main(args):
 MyClass().test_method(args)
 # Should throw an error

EDIT:

  • @staticmethod will work on both class instances like MyClass().test_method(args)and just a regular direct call like MyClass.test_method(args)
  • However a regular method(without self in it) can't be called on a class instance. So you will always have to call it as MyClass.test_method(args)
answered Oct 16, 2018 at 9:20

3 Comments

How is a normal function declared in a class different from a static method?
@Theod'Or It is identical to staticmethods, the only difference being, you can't call it on class instances.
@jar do you happen to know why Python provides these two types of static methods? (with and without decorators), e.g. what would be a good reason for restricting instance calls?
4

self isn't necessarily required. However, if you want to reference any variable or value that is associated with the object(instantiation of the class) (E.g. for a class about cars, it's speed, self.speed) you'll need to have self as a parameter in the function. For this reason, it's common practice to always have self as an argument, otherwise you aren't really using the class for the right reason.

EDIT: This will actually throw an error if you do the following:

class a():
 def __init__(self, x):
 self.asd = x
 def hello(x):
 print(x)
>>> g = a(4)
>>> g.hello(5)

as when calling "hello", both "self" and "4" will be passed as parameters. It would work in the following instance, which is what I was saying above:

>>> g = a
>>> g.hello(4)

or

>>> a.hello(4)
answered Oct 16, 2018 at 8:58

4 Comments

This isn't really true. self is required for an instance method, even if you don't use it, because it will be passed anyway; if the method doesn't accept it, you will get a TypeError.
Can you give me an example of some code that throws this error? Because the following: class a(): def hello(x): print(x) works fine
a.hello() would work, but then you're not calling it on an instance so you wouldn't expect to have self anyway. a().hello() would give that error.
You're right, I just tested it. That's really interesting, learn something new every day (:
2

To add on to the existing answers here and provide a code example:

class MyClass:
 def __init__(self):
 pass
 def myStaticMethod():
 print("a static method")
 @staticmethod
 def myStaticMethodWithArg(my_arg):
 print(my_arg)
 print("a static method")
MyClass.myStaticMethod()
MyClass.myStaticMethodWithArg("skhsdkj")
abc = MyClass()
abc.myStaticMethodWithArg("avc")

Try removing the @staticmethod decorator and rerunning the code and see what happens! (The very last call will fail since the method is passed in both self and the string input. By adding the decorator, we can guide the interpreter to perform our desired action)

answered Jun 20, 2020 at 17:10

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.