Reputation: 823
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?"
Upvotes: 14
Views: 14455
Reputation: 3118
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)
Upvotes: 2
Reputation: 1939
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)
Upvotes: 4
Reputation: 2908
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)
self
in it) can't be called on a class instance. So you will always have to call it as MyClass.test_method(args)
Upvotes: 6
Reputation: 599610
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.
Upvotes: 15