Hello everyone,
I was studying OOP and the concept of instances, class methods and static methods still confuses me.
I have watched tons of YouTube already but I can't find a person who explains it as dumb as possible because that is how I understand things.
Please if there is anyone who can recommend to me a video or explain it to me in the simplest way possible with examples, I will be glad :)
Note: I want the simplest form of explanation about the matter.
Videos
Title says it all.
I looked up static methods in Python and found this little article comparing class methods and static methods. The article states that class methods are designed to change the state of a class rather than an instance of a class. It also states that class methods are good for creating factory methods, and it shows this sample code:
# Python program to demonstrate
# use of class method and static method.
from datetime import date
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
# a class method to create a Person object by birth year.
@classmethod
def fromBirthYear(cls, name, year):
return cls(name, date.today().year - year)
# a static method to check if a Person is adult or not.
@staticmethod
def isAdult(age):
return age > 18
person1 = Person('mayank', 21)
person2 = Person.fromBirthYear('mayank', 1996)
print person1.age
print person2.age
# print the result
print Person.isAdult(22) Is there really a reason to use a class method rather than a static method for the fromBirthYear() method? The only advantage I can see is that the class name does not have to be used inside the method, so that if the class name changes the method does not have to change.
Hy Everyone,
My way of learning things is asking WHY any feature is there in any language. When I searched why for classmetohd and staticmethod in python. I found out how to use it and some intuition but not a clear answer. Please help me to understand it better.
Maybe a bit of example code will help: Notice the difference in the call signatures of foo, class_foo and static_foo:
class A(object):
def foo(self, x):
print(f"executing foo({self}, {x})")
@classmethod
def class_foo(cls, x):
print(f"executing class_foo({cls}, {x})")
@staticmethod
def static_foo(x):
print(f"executing static_foo({x})")
a = A()
Below is the usual way an object instance calls a method. The object instance, a, is implicitly passed as the first argument.
a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>, 1)
With classmethods, the class of the object instance is implicitly passed as the first argument instead of self.
a.class_foo(1)
# executing class_foo(<class '__main__.A'>, 1)
You can also call class_foo using the class. In fact, if you define something to be
a classmethod, it is probably because you intend to call it from the class rather than from a class instance. A.foo(1) would have raised a TypeError, but A.class_foo(1) works just fine:
A.class_foo(1)
# executing class_foo(<class '__main__.A'>, 1)
One use people have found for class methods is to create inheritable alternative constructors.
With staticmethods, neither self (the object instance) nor cls (the class) is implicitly passed as the first argument. They behave like plain functions except that you can call them from an instance or the class:
a.static_foo(1)
# executing static_foo(1)
A.static_foo('hi')
# executing static_foo(hi)
Staticmethods are used to group functions which have some logical connection with a class to the class.
foo is just a function, but when you call a.foo you don't just get the function,
you get a "partially applied" version of the function with the object instance a bound as the first argument to the function. foo expects 2 arguments, while a.foo only expects 1 argument.
a is bound to foo. That is what is meant by the term "bound" below:
print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>
With a.class_foo, a is not bound to class_foo, rather the class A is bound to class_foo.
print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>
Here, with a staticmethod, even though it is a method, a.static_foo just returns
a good 'ole function with no arguments bound. static_foo expects 1 argument, and
a.static_foo expects 1 argument too.
print(a.static_foo)
# <function static_foo at 0xb7d479cc>
And of course the same thing happens when you call static_foo with the class A instead.
print(A.static_foo)
# <function static_foo at 0xb7d479cc>
A staticmethod is a method that knows nothing about the class or instance it was called on. It just gets the arguments that were passed, no implicit first argument.
A classmethod, on the other hand, is a method that gets passed the class it was called on, or the class of the instance it was called on, as first argument. This is useful when you want the method to be a factory for the class: since it gets the actual class it was called on as first argument, you can always instantiate the right class, even when subclasses are involved. Observe for instance how dict.fromkeys(), a classmethod, returns an instance of the subclass when called on a subclass:
>>> class DictSubclass(dict):
... def __repr__(self):
... return "DictSubclass"
...
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>>
When searching for it on google, i get many explanations why it is different from classmethod. But noone explains what it does exactly. As far as i can tell, defining a function on the class itself has the same effect
class A:
@staticmethod
def f(x,y):
return x + y
def g(x,y):
return x + y
print(A.f(1,2))
print(A.g(1,2))Hey, so I am fairly new to python and programming. I came across the decorators \@classmethod and \@staticmethod. I understand the difference between them both, but when do I really use it. As far as I can comprehend, I cannot find reasons why to use them over stand alone functions.
For example, I creat a vector class, and I want to calculate the distance between vector 1 and vector 2, it seemed that I should use @classmethod, well, I did not success, and I can use @staticmethod, but I am not sure it is correct. here is my code
class Vector(object):
def __init__(self,x,y):
self.x = x
self.y = y
@classmethod
def distance_1(self,cls):
return (self.x-cls.x)**2 + (self.y-cls.y)**2
@staticmethod
def distance_2(self,cls):
return (self.x-cls.x)**2 + (self.y-cls.y)**2
if __name__ == '__main__':
a = Vector(1,1)
print(a.distance_1(Vector(2,2)))i've searched everywhere and gotten some answers but it still doesnt make 100% of sense to me what exactly are the purpose of these two??. any answers given to me is appreciated. please and thank you.
Class methods:
+Are not called from class members
+Do not alter member state
-Alters *class state for all members contained within
Static methods:
+Are not called from class members
+Do not alter member state
-Do not alter class state.
An example of a class method would be one that alters the output function of a class. Let's say you have a display_output() method for each class member. That method might use a class property called output_format. You may define a class method that alters the class output format, meaning the display format for all class members would change
class methods are also a useful way to construct logic which varies based on the attributes of subclasses
like here is a kinda shoddy example idk
import json
import yaml
class Animal:
raw_input_parser = json.loads
def __init__(self, name, age, species):
self.name = name
self.age = age
self.species = species
@classmethod
def from_raw_input(cls, raw_input):
return cls(**cls.raw_input_parser(raw_input))
class Yaminal(Animal):
raw_input_parser = yaml.safe_load
the classmethod is letting you define an entirely new class for parsing input without duplicating the rest of the code
I’m trying to get into more advanced OOP and there’s one question that keeps bugging me—is there any functional difference between a static method placed inside a class definition and a function that lives outside of the class? Is the former just for organization/convenience (e.g. the user gets the static method automatically when they import the class)?
I'm writing a class which has a couple of methods that the ide (pycharm) has flagged up could be static methods. I haven't really used these before.
(To confirm is a static method any method that doesn't use any of the objects attributes or methods?)
I'm not sure when a method should be a static method or a seperate function outside the class (or perhaps something else eg normal instance methods).
All of the (possible) static methods are used by other methods within the class.
One of them is used by a method (which calls several of the object methods in a particular sequence) and is used to convert output from one method to another. This feels like it it's definitely tied to the object, but not sure if it should be a static method or an instance method (it will only ever be used on an instance not on the class itself).
Other potential static methods are more like helper functions that I don't need elsewhere than that object but are used by some of the object methods. eg.
@staticmethod
def log_database_create(instance):
sys.stdout.write('New {} created \n'.format(instance.__class__.__name__))
@staticmethod
def log_database_update(instance):
sys.stdout.write('{}: updated \n'.format(instance.__class__.__name__))
@staticmethod
def make_int(string):
s = string.strip()
return int(s) if s else NoneI have been writing python heavily for a good 5 years or so, but I just now realized that this is possible:
class MyClass:
@staticmethod
def my_cool_static_func():
# do static things
def some_other_func(self):
# how strange, I can call a static method on a class instance...
self.my_cool_static_func()I'm encountering this exact pattern quite a bit in an old codebase for a company I just started working for, and I'm wondering why someone would do this? Why not make both of these static (or use a class method)?
class MyClass:
@staticmethod
def my_cool_static_func():
# do static things
@staticmethod
def some_other_func():
MyClass.my_cool_static_func()This second example seems a lot more familiar and logical to me coming from other languages. Is there a functional difference between these two? Is there a non-functional reason one might want to (or even should) write the first example over the second? I'm kinda prejudiced against example one; if I see `self.some_func()` I immediately think "ah an instance method that needs instance state", so I don't love the ambiguity created by being able to call a static method this way, but I'd like to understand this first. Why is the first example even possible in python? If its just a byproduct of some internal language design thing, is it actually useful for anything? Should it be avoided?
I was wondering what would be the benefits of using `@staticmethod` or `@classmethod`.
Decided to measure their execution speed.
Turns out they are slightly slower than module level function and much faster than usual class method:
Difference in speed of execution of different types of methods in Python
-
Without initiating class, when possible:
| Method Type | time in seconds |
|---|---|
| function | 1.469 |
| method | 4.370 |
| class_method | 1.869 |
| static_method | 1.653 |
| property_method | 4.471 |
-
Initiating classes
| Method Type | time in seconds |
|---|---|
| function | 1.462 |
| method | 4.503 |
| class_method | 2.641 |
| static_method | 2.379 |
| property_method | 4.382 |
https://github.com/almazkun/methods_speed
If your method calls a static method on the class, then it does require information on the class. You have a class method, not a static method. By declaring it @classmethod (and adding the cls parameter), you not only properly inform the reader, you allow polymorphism. An inheritor can reimplement the called static method and change behavior.
Python's static methods are intended for methods that are part of a class, and can be called as either a class method or an instance method: both Class.the_method() and self.the_method() would work. When the static method is called, it is not given an implicit first argument:
class Example:
def instance_method_example(self, arguments):
...
@classmethod
def class_method_example(cls, arguments):
...
@staticmethod
def static_method_example(arguments):
...
If you merely want to create a helper function that is used within your class, do not use @staticmethod. Define a free function outside of the class. For example:
class Example:
def some_method(self, argument):
return _helper(argument, self.x)
def _helper(a, b):
...
The background of static methods in Python is the following: when you access an attribute of an object x.attribute or getattr(x, 'attribute'), then this name is looked up in the instance dict or the class dict. If an object is found in the class dict, it is checked whether that object is a “descriptor”: an object that describes how this attribute behaves, not an object that would be directly returned. Descriptors have dunder-methods like __get__, __set__, and __del__ that are invoked depending on whether the descriptor is accessed, assigned to, or deleted with the del operator.
Functions – the things you declare with def – are descriptors. By default, the __get__ descriptor binds the function to the instance argument (typically called self) and returns the bound function, so that it can be invoked as a method. But the various decorators change this behaviour:
- a
@classmethod defbinds to the class object, not the instance - a
@staticmethod defdoes not bind to any object and just returns the underlying function directly - a
@propertyinvokes the underlying function to retrieve a value
These differences are (partially) visible when looking at the repr() of the bound methods. With the first Example class:
instance_method_example- with class:
Example.instance_method_example
is<function Example.instance_method_example at 0x7f1dfdd6fd30>,
the unbound function - with instance:
<function Example.instance_method_example at 0x7f1dfdd6fd30>
is<bound method Example.instance_method_example of <__main__.Example object at 0x7f1dfdddcb80>>,
a method bound to the instance
- with class:
class_method_example- with class:
Example.class_method_example
is<bound method Example.class_method_example of <class '__main__.Example'>>,
a method bound to the class - with instance:
Example().class_method_example
is<bound method Example.class_method_example of <class '__main__.Example'>>,
also a method bound to the class
- with class:
static_method_example- with class:
Example.static_method_example
is<function Example.static_method_example at 0x7f1dfdd6fe50>,
the unbound function - with instance:
Example().static_method_example
is<function Example.static_method_example at 0x7f1dfdd6fe50>,
also the unbound function
- with class:
As a table:
| invoked on… | no decorator | @classmethod |
@staticmethod |
|---|---|---|---|
| … instance | bound to instance | bound to class | unbound |
| … class | unbound | bound to class | unbound |