What is the difference between a method decorated with #staticmethod and one decorated with #classmethod?
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. It is basically useless in Python -- you can just use a module function instead of a staticmethod.
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
>>>
Basically #classmethod makes a method whose first argument is the class it's called from (rather than the class instance), #staticmethod does not have any implicit arguments.
To decide whether to use #staticmethod or #classmethod you have to look inside your method. If your method accesses other variables/methods in your class then use #classmethod. On the other hand, if your method does not touches any other parts of the class then use #staticmethod.
class Apple:
_counter = 0
#staticmethod
def about_apple():
print('Apple is good for you.')
# note you can still access other member of the class
# but you have to use the class instance
# which is not very nice, because you have repeat yourself
#
# For example:
# #staticmethod
# print('Number of apples have been juiced: %s' % Apple._counter)
#
# #classmethod
# print('Number of apples have been juiced: %s' % cls._counter)
#
# #classmethod is especially useful when you move your function to another class,
# you don't have to rename the referenced class
#classmethod
def make_apple_juice(cls, number_of_apples):
print('Making juice:')
for i in range(number_of_apples):
cls._juice_this(i)
#classmethod
def _juice_this(cls, apple):
print('Juicing apple %d...' % apple)
cls._counter += 1
Official python docs:
#classmethod
A class method receives the class as
implicit first argument, just like an
instance method receives the instance.
To declare a class method, use this
idiom:
class C:
#classmethod
def f(cls, arg1, arg2, ...): ...
The #classmethod form is a function
decorator – see the description of
function definitions in Function
definitions for details.
It can be called either on the class
(such as C.f()) or on an instance
(such as C().f()). The instance is
ignored except for its class. If a
class method is called for a derived
class, the derived class object is
passed as the implied first argument.
Class methods are different than C++
or Java static methods. If you want
those, see staticmethod() in this
section.
#staticmethod
A static method does not receive an
implicit first argument. To declare a
static method, use this idiom:
class C:
#staticmethod
def f(arg1, arg2, ...): ...
The #staticmethod form is a function
decorator – see the description of
function definitions in Function
definitions for details.
It can be called either on the class
(such as C.f()) or on an instance
(such as C().f()). The instance is
ignored except for its class.
Static methods in Python are similar
to those found in Java or C++. For a
more advanced concept, see
classmethod() in this section.
Here is a short article on this question
#staticmethod function is nothing more than a function defined inside a class. It is callable without instantiating the class first. It’s definition is immutable via inheritance.
#classmethod function also callable without instantiating the class, but its definition follows Sub class, not Parent class, via inheritance. That’s because the first argument for #classmethod function must always be cls (class).
What is the difference between #staticmethod and #classmethod in Python?
You may have seen Python code like this pseudocode, which demonstrates the signatures of the various method types and provides a docstring to explain each:
class Foo(object):
def a_normal_instance_method(self, arg_1, kwarg_2=None):
'''
Return a value that is a function of the instance with its
attributes, and other arguments such as arg_1 and kwarg2
'''
#staticmethod
def a_static_method(arg_0):
'''
Return a value that is a function of arg_0. It does not know the
instance or class it is called from.
'''
#classmethod
def a_class_method(cls, arg1):
'''
Return a value that is a function of the class and other arguments.
respects subclassing, it is called with the class it is called from.
'''
The Normal Instance Method
First I'll explain a_normal_instance_method. This is precisely called an "instance method". When an instance method is used, it is used as a partial function (as opposed to a total function, defined for all values when viewed in source code) that is, when used, the first of the arguments is predefined as the instance of the object, with all of its given attributes. It has the instance of the object bound to it, and it must be called from an instance of the object. Typically, it will access various attributes of the instance.
For example, this is an instance of a string:
', '
if we use the instance method, join on this string, to join another iterable,
it quite obviously is a function of the instance, in addition to being a function of the iterable list, ['a', 'b', 'c']:
>>> ', '.join(['a', 'b', 'c'])
'a, b, c'
Bound methods
Instance methods can be bound via a dotted lookup for use later.
For example, this binds the str.join method to the ':' instance:
>>> join_with_colons = ':'.join
And later we can use this as a function that already has the first argument bound to it. In this way, it works like a partial function on the instance:
>>> join_with_colons('abcde')
'a:b:c:d:e'
>>> join_with_colons(['FF', 'FF', 'FF', 'FF', 'FF', 'FF'])
'FF:FF:FF:FF:FF:FF'
Static Method
The static method does not take the instance as an argument.
It is very similar to a module level function.
However, a module level function must live in the module and be specially imported to other places where it is used.
If it is attached to the object, however, it will follow the object conveniently through importing and inheritance as well.
An example of a static method is str.maketrans, moved from the string module in Python 3. It makes a translation table suitable for consumption by str.translate. It does seem rather silly when used from an instance of a string, as demonstrated below, but importing the function from the string module is rather clumsy, and it's nice to be able to call it from the class, as in str.maketrans
# demonstrate same function whether called from instance or not:
>>> ', '.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
>>> str.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
In python 2, you have to import this function from the increasingly less useful string module:
>>> import string
>>> 'ABCDEFG'.translate(string.maketrans('ABC', 'abc'))
'abcDEFG'
Class Method
A class method is a similar to an instance method in that it takes an implicit first argument, but instead of taking the instance, it takes the class. Frequently these are used as alternative constructors for better semantic usage and it will support inheritance.
The most canonical example of a builtin classmethod is dict.fromkeys. It is used as an alternative constructor of dict, (well suited for when you know what your keys are and want a default value for them.)
>>> dict.fromkeys(['a', 'b', 'c'])
{'c': None, 'b': None, 'a': None}
When we subclass dict, we can use the same constructor, which creates an instance of the subclass.
>>> class MyDict(dict): 'A dict subclass, use to demo classmethods'
>>> md = MyDict.fromkeys(['a', 'b', 'c'])
>>> md
{'a': None, 'c': None, 'b': None}
>>> type(md)
<class '__main__.MyDict'>
See the pandas source code for other similar examples of alternative constructors, and see also the official Python documentation on classmethod and staticmethod.
I started learning programming language with C++ and then Java and then Python and so this question bothered me a lot as well, until I understood the simple usage of each.
Class Method: Python unlike Java and C++ doesn't have constructor overloading. And so to achieve this you could use classmethod. Following example will explain this
Let's consider we have a Person class which takes two arguments first_name and last_name and creates the instance of Person.
class Person(object):
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
Now, if the requirement comes where you need to create a class using a single name only, just a first_name, you can't do something like this in Python.
This will give you an error when you will try to create an object (instance).
class Person(object):
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
def __init__(self, first_name):
self.first_name = first_name
However, you could achieve the same thing using #classmethod as mentioned below
class Person(object):
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
#classmethod
def get_person(cls, first_name):
return cls(first_name, "")
Static Method: This is rather simple, it's not bound to instance or class and you can simply call that using class name.
So let's say in above example you need a validation that first_name should not exceed 20 characters, you can simply do this.
#staticmethod
def validate_name(name):
return len(name) <= 20
and you could simply call using class name
Person.validate_name("Gaurang Shah")
Only the first argument differs:
normal method: the current object is automatically passed as an (additional) first argument
classmethod: the class of the current object is automatically passed as an (additional) fist argument
staticmethod: no extra arguments are automatically passed. What you passed to the function is what you get.
In more detail...
normal method
The "standard" method, as in every object oriented language. When an object's method is called, it is automatically given an extra argument self as its first argument. That is, method
def f(self, x, y)
must be called with 2 arguments. self is automatically passed, and it is the object itself. Similar to the this that magically appears in eg. java/c++, only in python it is shown explicitly.
actually, the first argument does not have to be called self, but it's the standard convention, so keep it
class method
When the method is decorated
#classmethod
def f(cls, x, y)
the automatically provided argument is not self, but the class of self.
static method
When the method is decorated
#staticmethod
def f(x, y)
the method is not given any automatic argument at all. It is only given the parameters that it is called with.
usages
classmethod is mostly used for alternative constructors.
staticmethod does not use the state of the object, or even the structure of the class itself. It could be a function external to a class. It only put inside the class for grouping functions with similar functionality (for example, like Java's Math class static methods)
class Point
def __init__(self, x, y):
self.x = x
self.y = y
#classmethod
def frompolar(cls, radius, angle):
"""The `cls` argument is the `Point` class itself"""
return cls(radius * cos(angle), radius * sin(angle))
#staticmethod
def angle(x, y):
"""this could be outside the class, but we put it here
just because we think it is logically related to the class."""
return atan(y, x)
p1 = Point(3, 2)
p2 = Point.frompolar(3, pi/4)
angle = Point.angle(3, 2)
I think a better question is "When would you use #classmethod vs #staticmethod?"
#classmethod allows you easy access to private members that are associated to the class definition. this is a great way to do singletons, or factory classes that control the number of instances of the created objects exist.
#staticmethod provides marginal performance gains, but I have yet to see a productive use of a static method within a class that couldn't be achieved as a standalone function outside the class.
Static Methods:
Simple functions with no self argument.
Work on class attributes; not on instance attributes.
Can be called through both class and instance.
The built-in function staticmethod()is used to create them.
Benefits of Static Methods:
It localizes the function name in the classscope
It moves the function code closer to where it is used
More convenient to import versus module-level functions since each method does not have to be specially imported
#staticmethod
def some_static_method(*args, **kwds):
pass
Class Methods:
Functions that have first argument as classname.
Can be called through both class and instance.
These are created with classmethod in-built function.
#classmethod
def some_class_method(cls, *args, **kwds):
pass
#decorators were added in python 2.4 If you're using python < 2.4 you can use the classmethod() and staticmethod() function.
For example, if you want to create a factory method (A function returning an instance of a different implementation of a class depending on what argument it gets) you can do something like:
class Cluster(object):
def _is_cluster_for(cls, name):
"""
see if this class is the cluster with this name
this is a classmethod
"""
return cls.__name__ == name
_is_cluster_for = classmethod(_is_cluster_for)
#static method
def getCluster(name):
"""
static factory method, should be in Cluster class
returns a cluster object for the given name
"""
for cls in Cluster.__subclasses__():
if cls._is_cluster_for(name):
return cls()
getCluster = staticmethod(getCluster)
Also observe that this is a good example for using a classmethod and a static method,
The static method clearly belongs to the class, since it uses the class Cluster internally.
The classmethod only needs information about the class, and no instance of the object.
Another benefit of making the _is_cluster_for method a classmethod is so a subclass can decide to change it's implementation, maybe because it is pretty generic and can handle more than one type of cluster, so just checking the name of the class would not be enough.
Let me tell the similarity between a method decorated with #classmethod vs #staticmethod first.
Similarity: Both of them can be called on the Class itself, rather than just the instance of the class. So, both of them in a sense are Class's methods.
Difference: A classmethod will receive the class itself as the first argument, while a staticmethod does not.
So a static method is, in a sense, not bound to the Class itself and is just hanging in there just because it may have a related functionality.
>>> class Klaus:
#classmethod
def classmthd(*args):
return args
#staticmethod
def staticmthd(*args):
return args
# 1. Call classmethod without any arg
>>> Klaus.classmthd()
(__main__.Klaus,) # the class gets passed as the first argument
# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')
# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()
()
# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)
#staticmethod just disables the default function as method descriptor. classmethod wraps your function in a container callable that passes a reference to the owning class as first argument:
>>> class C(object):
... pass
...
>>> def f():
... pass
...
>>> staticmethod(f).__get__(None, C)
<function f at 0x5c1cf0>
>>> classmethod(f).__get__(None, C)
<bound method type.f of <class '__main__.C'>>
As a matter of fact, classmethod has a runtime overhead but makes it possible to access the owning class. Alternatively I recommend using a metaclass and putting the class methods on that metaclass:
>>> class CMeta(type):
... def foo(cls):
... print cls
...
>>> class C(object):
... __metaclass__ = CMeta
...
>>> C.foo()
<class '__main__.C'>
Another consideration with respect to staticmethod vs classmethod comes up with inheritance. Say you have the following class:
class Foo(object):
#staticmethod
def bar():
return "In Foo"
And you then want to override bar() in a child class:
class Foo2(Foo):
#staticmethod
def bar():
return "In Foo2"
This works, but note that now the bar() implementation in the child class (Foo2) can no longer take advantage of anything specific to that class. For example, say Foo2 had a method called magic() that you want to use in the Foo2 implementation of bar():
class Foo2(Foo):
#staticmethod
def bar():
return "In Foo2"
#staticmethod
def magic():
return "Something useful you'd like to use in bar, but now can't"
The workaround here would be to call Foo2.magic() in bar(), but then you're repeating yourself (if the name of Foo2 changes, you'll have to remember to update that bar() method).
To me, this is a slight violation of the open/closed principle, since a decision made in Foo is impacting your ability to refactor common code in a derived class (ie it's less open to extension). If bar() were a classmethod we'd be fine:
class Foo(object):
#classmethod
def bar(cls):
return "In Foo"
class Foo2(Foo):
#classmethod
def bar(cls):
return "In Foo2 " + cls.magic()
#classmethod
def magic(cls):
return "MAGIC"
print Foo2().bar()
Gives: In Foo2 MAGIC
Also: historical note: Guido Van Rossum (Python's creator) once referred to staticmethod's as "an accident": https://mail.python.org/pipermail/python-ideas/2012-May/014969.html
we all know how limited static methods are. (They're basically an accident -- back in the Python 2.2 days when I was inventing new-style classes and descriptors, I meant to implement class methods but at first I didn't understand them and accidentally implemented static methods first. Then it was too late to remove them and only provide class methods.
Also: https://mail.python.org/pipermail/python-ideas/2016-July/041189.html
Honestly, staticmethod was something of a mistake -- I was trying to do something like Java class methods but once it was released I found what was really needed was classmethod. But it was too late to get rid of staticmethod.
The definitive guide on how to use static, class or abstract methods in Python is one good link for this topic, and summary it as following.
#staticmethod function is nothing more than a function defined inside a class. It is callable without instantiating the class first. It’s definition is immutable via inheritance.
Python does not have to instantiate a bound-method for object.
It eases the readability of the code, and it does not depend on the state of object itself;
#classmethod function also callable without instantiating the class, but its definition follows Sub class, not Parent class, via inheritance, can be overridden by subclass. That’s because the first argument for #classmethod function must always be cls (class).
Factory methods, that are used to create an instance for a class using for example some sort of pre-processing.
Static methods calling static methods: if you split a static methods in several static methods, you shouldn't hard-code the class name but use class methods
I will try to explain the basic difference using an example.
class A(object):
x = 0
def say_hi(self):
pass
#staticmethod
def say_hi_static():
pass
#classmethod
def say_hi_class(cls):
pass
def run_self(self):
self.x += 1
print self.x # outputs 1
self.say_hi()
self.say_hi_static()
self.say_hi_class()
#staticmethod
def run_static():
print A.x # outputs 0
# A.say_hi() # wrong
A.say_hi_static()
A.say_hi_class()
#classmethod
def run_class(cls):
print cls.x # outputs 0
# cls.say_hi() # wrong
cls.say_hi_static()
cls.say_hi_class()
1 - we can directly call static and classmethods without initializing
# A.run_self() # wrong
A.run_static()
A.run_class()
2- Static method cannot call self method but can call other static and classmethod
3- Static method belong to class and will not use object at all.
4- Class method are not bound to an object but to a class.
The difference occurs when there is inheritance.
Suppose that there are two classes-- Parent and Child. If one wants to use #staticmethod, print_name method should be written twice because the name of the class should be written in the print line.
class Parent:
_class_name = "Parent"
#staticmethod
def print_name():
print(Parent._class_name)
class Child(Parent):
_class_name = "Child"
#staticmethod
def print_name():
print(Child._class_name)
Parent.print_name()
Child.print_name()
However, for #classmethod, it is not required to write print_name method twice.
class Parent:
_class_name = "Parent"
#classmethod
def print_name(cls):
print(cls._class_name)
class Child(Parent):
_class_name = "Child"
Parent.print_name()
Child.print_name()
Python comes with several built-in decorators. The big three are:
#classmethod
#staticmethod
#property
First let's note that any function of a class can be called with instance of this class (after we initialized this class).
#classmethod is the way to call function not only as an instance of a class but also directly by the class itself as its first argument.
#staticmethod is a way of putting a function into a class (because it logically belongs there), while indicating that it does not require access to the class (so we don't need to use self in function definition).
Let's consider the following class:
class DecoratorTest(object):
def __init__(self):
pass
def doubler(self, x):
return x*2
#classmethod
def class_doubler(cls, x): # we need to use 'cls' instead of 'self'; 'cls' reference to the class instead of an instance of the class
return x*2
#staticmethod
def static_doubler(x): # no need adding 'self' here; static_doubler() could be just a function not inside the class
return x*2
Let's see how it works:
decor = DecoratorTest()
print(decor.doubler(5))
# 10
print(decor.class_doubler(5)) # a call with an instance of a class
# 10
print(DecoratorTest.class_doubler(5)) # a direct call by the class itself
# 10
# staticmethod could be called in the same way as classmethod.
print(decor.static_doubler(5)) # as an instance of the class
# 10
print(DecoratorTest.static_doubler(5)) # or as a direct call
# 10
Here you can see some use cases for those methods.
Bonus: you can read about #property decorator here
Instance Method:
+ Can modify object instance state
+ Can modify class state
Class Method:
- Can't modify object instance state
+ Can modify class state
Static Method:
- Can't modify object instance state
- Can't modify class state
class MyClass:
'''
Instance method has a mandatory first attribute self which represent the instance itself.
Instance method must be called by a instantiated instance.
'''
def method(self):
return 'instance method called', self
'''
Class method has a mandatory first attribute cls which represent the class itself.
Class method can be called by an instance or by the class directly.
Its most common using scenario is to define a factory method.
'''
#classmethod
def class_method(cls):
return 'class method called', cls
'''
Static method doesn’t have any attributes of instances or the class.
It also can be called by an instance or by the class directly.
Its most common using scenario is to define some helper or utility functions which are closely relative to the class.
'''
#staticmethod
def static_method():
return 'static method called'
obj = MyClass()
print(obj.method())
print(obj.class_method()) # MyClass.class_method()
print(obj.static_method()) # MyClass.static_method()
output:
('instance method called', <__main__.MyClass object at 0x100fb3940>)
('class method called', <class '__main__.MyClass'>)
static method called
The instance method we actually had access to the object instance , right so this was an instance off a my class object whereas with the class method we have access to the class itself. But not to any of the objects, because the class method doesn't really care about an object existing. However you can both call a class method and static method on an object instance. This is going to work it doesn't really make a difference, so again when you call static method here it's going to work and it's going to know which method you want to call.
The Static methods are used to do some utility tasks, and class methods are used for factory methods. The factory methods can return class objects for different use cases.
And finally, a short example for better understanding:
class Student:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
#classmethod
def get_from_string(cls, name_string: str):
first_name, last_name = name_string.split()
if Student.validate_name(first_name) and Student.validate_name(last_name):
return cls(first_name, last_name)
else:
print('Invalid Names')
#staticmethod
def validate_name(name):
return len(name) <= 10
stackoverflow_student = Student.get_from_string('Name Surname')
print(stackoverflow_student.first_name) # Name
print(stackoverflow_student.last_name) # Surname
#classmethod : can be used to create a shared global access to all the instances created of that class..... like updating a record by multiple users....
I particulary found it use ful when creating singletons as well..:)
#static method: has nothing to do with the class or instance being associated with ...but for readability can use static method
My contribution demonstrates the difference amongst #classmethod, #staticmethod, and instance methods, including how an instance can indirectly call a #staticmethod. But instead of indirectly calling a #staticmethod from an instance, making it private may be more "pythonic." Getting something from a private method isn't demonstrated here but it's basically the same concept.
#!python3
from os import system
system('cls')
# % % % % % % % % % % % % % % % % % % % %
class DemoClass(object):
# instance methods need a class instance and
# can access the instance through 'self'
def instance_method_1(self):
return 'called from inside the instance_method_1()'
def instance_method_2(self):
# an instance outside the class indirectly calls the static_method
return self.static_method() + ' via instance_method_2()'
# class methods don't need a class instance, they can't access the
# instance (self) but they have access to the class itself via 'cls'
#classmethod
def class_method(cls):
return 'called from inside the class_method()'
# static methods don't have access to 'cls' or 'self', they work like
# regular functions but belong to the class' namespace
#staticmethod
def static_method():
return 'called from inside the static_method()'
# % % % % % % % % % % % % % % % % % % % %
# works even if the class hasn't been instantiated
print(DemoClass.class_method() + '\n')
''' called from inside the class_method() '''
# works even if the class hasn't been instantiated
print(DemoClass.static_method() + '\n')
''' called from inside the static_method() '''
# % % % % % % % % % % % % % % % % % % % %
# >>>>> all methods types can be called on a class instance <<<<<
# instantiate the class
democlassObj = DemoClass()
# call instance_method_1()
print(democlassObj.instance_method_1() + '\n')
''' called from inside the instance_method_1() '''
# # indirectly call static_method through instance_method_2(), there's really no use
# for this since a #staticmethod can be called whether the class has been
# instantiated or not
print(democlassObj.instance_method_2() + '\n')
''' called from inside the static_method() via instance_method_2() '''
# call class_method()
print(democlassObj.class_method() + '\n')
''' called from inside the class_method() '''
# call static_method()
print(democlassObj.static_method())
''' called from inside the static_method() '''
"""
# whether the class is instantiated or not, this doesn't work
print(DemoClass.instance_method_1() + '\n')
'''
TypeError: TypeError: unbound method instancemethod() must be called with
DemoClass instance as first argument (got nothing instead)
'''
"""
A class method receives the class as implicit first argument, just like an instance method receives the instance. It is a method which is bound to the class and not the object of the class.It has access to the state of the class as it takes a class parameter that points to the class and not the object instance. It can modify a class state that would apply across all the instances of the class. For example it can modify a class variable that will be applicable to all the instances.
On the other hand, a static method does not receive an implicit first argument, compared to class methods or instance methods. And can’t access or modify class state. It only belongs to the class because from design point of view that is the correct way. But in terms of functionality is not bound, at runtime, to the class.
as a guideline, use static methods as utilities, use class methods for example as factory . Or maybe to define a singleton. And use instance methods to model the state and behavior of instances.
Hope I was clear !
You might want to consider the difference between:
class A:
def foo(): # no self parameter, no decorator
pass
and
class B:
#staticmethod
def foo(): # no self parameter
pass
This has changed between python2 and python3:
python2:
>>> A.foo()
TypeError
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()
python3:
>>> A.foo()
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()
So using #staticmethod for methods only called directly from the class has become optional in python3. If you want to call them from both class and instance, you still need to use the #staticmethod decorator.
The other cases have been well covered by unutbus answer.
Class methods, as the name suggests, are used to make changes to classes and not the objects. To make changes to classes, they will modify the class attributes(not object attributes), since that is how you update classes.
This is the reason that class methods take the class(conventionally denoted by 'cls') as the first argument.
class A(object):
m=54
#classmethod
def class_method(cls):
print "m is %d" % cls.m
Static methods on the other hand, are used to perform functionalities that are not bound to the class i.e. they will not read or write class variables. Hence, static methods do not take classes as arguments. They are used so that classes can perform functionalities that are not directly related to the purpose of the class.
class X(object):
m=54 #will not be referenced
#staticmethod
def static_method():
print "Referencing/calling a variable or function outside this class. E.g. Some global variable/function."
I think giving a purely Python version of staticmethod and classmethod would help to understand the difference between them at language level (Refers to Descriptor Howto Guide).
Both of them are non-data descriptors (It would be easier to understand them if you are familiar with descriptors first).
class StaticMethod(object):
"Emulate PyStaticMethod_Type() in Objects/funcobject.c"
def __init__(self, f):
self.f = f
def __get__(self, obj, objtype=None):
return self.f
class ClassMethod(object):
"Emulate PyClassMethod_Type() in Objects/funcobject.c"
def __init__(self, f):
self.f = f
def __get__(self, obj, cls=None):
def inner(*args, **kwargs):
if cls is None:
cls = type(obj)
return self.f(cls, *args, **kwargs)
return inner
Analyze #staticmethod literally providing different insights.
A normal method of a class is an implicit dynamic method which takes the instance as first argument.
In contrast, a staticmethod does not take the instance as first argument, so is called 'static'.
A staticmethod is indeed such a normal function the same as those outside a class definition.
It is luckily grouped into the class just in order to stand closer where it is applied, or you might scroll around to find it.
One pretty important practical difference occurs when subclassing. If you don't mind, I'll hijack #unutbu's example:
class A:
def foo(self, x):
print("executing foo(%s, %s)" % (self, x))
#classmethod
def class_foo(cls, x):
print("executing class_foo(%s, %s)" % (cls, x))
#staticmethod
def static_foo(x):
print("executing static_foo(%s)" % x)
class B(A):
pass
In class_foo, the method knows which class it is called on:
A.class_foo(1)
# => executing class_foo(<class '__main__.A'>, 1)
B.class_foo(1)
# => executing class_foo(<class '__main__.B'>, 1)
In static_foo, there is no way to determine whether it is called on A or B:
A.static_foo(1)
# => executing static_foo(1)
B.static_foo(1)
# => executing static_foo(1)
Note that this doesn't mean you can't use other methods in a staticmethod, you just have to reference the class directly, which means subclasses' staticmethods will still reference the parent class:
class A:
#classmethod
def class_qux(cls, x):
print(f"executing class_qux({cls}, {x})")
#classmethod
def class_bar(cls, x):
cls.class_qux(x)
#staticmethod
def static_bar(x):
A.class_qux(x)
class B(A):
pass
A.class_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
B.class_bar(1)
# => executing class_qux(<class '__main__.B'>, 1)
A.static_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
B.static_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
tldr;
A staticmethod is essentially a function bound to a class (and consequently its instances)
A classmethod is essentially an inheritable staticmethod.
For details, see the excellent answers by others.
First let's start with an example code that we'll use to understand both concepts:
class Employee:
NO_OF_EMPLOYEES = 0
def __init__(self, first_name, last_name, salary):
self.first_name = first_name
self.last_name = last_name
self.salary = salary
self.increment_employees()
def give_raise(self, amount):
self.salary += amount
#classmethod
def employee_from_full_name(cls, full_name, salary):
split_name = full_name.split(' ')
first_name = split_name[0]
last_name = split_name[1]
return cls(first_name, last_name, salary)
#classmethod
def increment_employees(cls):
cls.NO_OF_EMPLOYEES += 1
#staticmethod
def get_employee_legal_obligations_txt():
legal_obligations = """
1. An employee must complete 8 hours per working day
2. ...
"""
return legal_obligations
Class method
A class method accepts the class itself as an implicit argument and -optionally- any other arguments specified in the definition. It’s important to understand that a class method, does not have access to object instances (like instance methods do). Therefore, class methods cannot be used to alter the state of an instantiated object but instead, they are capable of changing the class state which is shared amongst all the instances of that class.
Class methods are typically useful when we need to access the class itself — for example, when we want to create a factory method, that is a method that creates instances of the class. In other words, class methods can serve as alternative constructors.
In our example code, an instance of Employee can be constructed by providing three arguments; first_name , last_name and salary.
employee_1 = Employee('Andrew', 'Brown', 85000)
print(employee_1.first_name)
print(employee_1.salary)
'Andrew'
85000
Now let’s assume that there’s a chance that the name of an Employee can be provided in a single field in which the first and last names are separated by a whitespace. In this case, we could possibly use our class method called employee_from_full_name that accepts three arguments in total. The first one, is the class itself, which is an implicit argument which means that it won’t be provided when calling the method — Python will automatically do this for us:
employee_2 = Employee.employee_from_full_name('John Black', 95000)
print(employee_2.first_name)
print(employee_2.salary)
'John'
95000
Note that it is also possible to call employee_from_full_name from object instances although in this context it doesn’t make a lot of sense:
employee_1 = Employee('Andrew', 'Brown', 85000)
employee_2 = employee_1.employee_from_full_name('John Black', 95000)
Another reason why we might want to create a class method, is when we need to change the state of the class. In our example, the class variable NO_OF_EMPLOYEES keeps track of the number of employees currently working for the company. This method is called every time a new instance of Employee is created and it updates the count accordingly:
employee_1 = Employee('Andrew', 'Brown', 85000)
print(f'Number of employees: {Employee.NO_OF_EMPLOYEES}')
employee_2 = Employee.employee_from_full_name('John Black', 95000)
print(f'Number of employees: {Employee.NO_OF_EMPLOYEES}')
Number of employees: 1
Number of employees: 2
Static methods
On the other hand, in static methods neither the instance (i.e. self) nor the class itself (i.e. cls) is passed as an implicit argument. This means that such methods, are not capable of accessing the class itself or its instances.
Now one could argue that static methods are not useful in the context of classes as they can also be placed in helper modules instead of adding them as members of the class. In object oriented programming, it is important to structure your classes into logical chunks and thus, static methods are quite useful when we need to add a method under a class simply because it logically belongs to the class.
In our example, the static method named get_employee_legal_obligations_txt simply returns a string that contains the legal obligations of every single employee of a company. This function, does not interact with the class itself nor with any instance. It could have been placed into a different helper module however, it is only relevant to this class and therefore we have to place it under the Employee class.
A static method can be access directly from the class itself
print(Employee.get_employee_legal_obligations_txt())
1. An employee must complete 8 hours per working day
2. ...
or from an instance of the class:
employee_1 = Employee('Andrew', 'Brown', 85000)
print(employee_1.get_employee_legal_obligations_txt())
1. An employee must complete 8 hours per working day
2. ...
References
What's the difference between static and class methods in Python?
What's the difference between:
class Child(SomeBaseClass):
def __init__(self):
super(Child, self).__init__()
and:
class Child(SomeBaseClass):
def __init__(self):
SomeBaseClass.__init__(self)
I've seen super being used quite a lot in classes with only single inheritance. I can see why you'd use it in multiple inheritance but am unclear as to what the advantages are of using it in this kind of situation.
What's the difference?
SomeBaseClass.__init__(self)
means to call SomeBaseClass's __init__. while
super().__init__()
means to call a bound __init__ from the parent class that follows SomeBaseClass's child class (the one that defines this method) in the instance's Method Resolution Order (MRO).
If the instance is a subclass of this child class, there may be a different parent that comes next in the MRO.
Explained simply
When you write a class, you want other classes to be able to use it. super() makes it easier for other classes to use the class you're writing.
As Bob Martin says, a good architecture allows you to postpone decision making as long as possible.
super() can enable that sort of architecture.
When another class subclasses the class you wrote, it could also be inheriting from other classes. And those classes could have an __init__ that comes after this __init__ based on the ordering of the classes for method resolution.
Without super you would likely hard-code the parent of the class you're writing (like the example does). This would mean that you would not call the next __init__ in the MRO, and you would thus not get to reuse the code in it.
If you're writing your own code for personal use, you may not care about this distinction. But if you want others to use your code, using super is one thing that allows greater flexibility for users of the code.
Python 2 versus 3
This works in Python 2 and 3:
super(Child, self).__init__()
This only works in Python 3:
super().__init__()
It works with no arguments by moving up in the stack frame and getting the first argument to the method (usually self for an instance method or cls for a class method - but could be other names) and finding the class (e.g. Child) in the free variables (it is looked up with the name __class__ as a free closure variable in the method).
I used to prefer to demonstrate the cross-compatible way of using super, but now that Python 2 is largely deprecated, I will demonstrate the Python 3 way of doing things, that is, calling super with no arguments.
Indirection with Forward Compatibility
What does it give you? For single inheritance, the examples from the question are practically identical from a static analysis point of view. However, using super gives you a layer of indirection with forward compatibility.
Forward compatibility is very important to seasoned developers. You want your code to keep working with minimal changes as you change it. When you look at your revision history, you want to see precisely what changed when.
You may start off with single inheritance, but if you decide to add another base class, you only have to change the line with the bases - if the bases change in a class you inherit from (say a mixin is added) you'd change nothing in this class.
In Python 2, getting the arguments to super and the correct method arguments right can be a little confusing, so I suggest using the Python 3 only method of calling it.
If you know you're using super correctly with single inheritance, that makes debugging less difficult going forward.
Dependency Injection
Other people can use your code and inject parents into the method resolution:
class SomeBaseClass(object):
def __init__(self):
print('SomeBaseClass.__init__(self) called')
class UnsuperChild(SomeBaseClass):
def __init__(self):
print('UnsuperChild.__init__(self) called')
SomeBaseClass.__init__(self)
class SuperChild(SomeBaseClass):
def __init__(self):
print('SuperChild.__init__(self) called')
super().__init__()
Say you add another class to your object, and want to inject a class between Foo and Bar (for testing or some other reason):
class InjectMe(SomeBaseClass):
def __init__(self):
print('InjectMe.__init__(self) called')
super().__init__()
class UnsuperInjector(UnsuperChild, InjectMe): pass
class SuperInjector(SuperChild, InjectMe): pass
Using the un-super child fails to inject the dependency because the child you're using has hard-coded the method to be called after its own:
>>> o = UnsuperInjector()
UnsuperChild.__init__(self) called
SomeBaseClass.__init__(self) called
However, the class with the child that uses super can correctly inject the dependency:
>>> o2 = SuperInjector()
SuperChild.__init__(self) called
InjectMe.__init__(self) called
SomeBaseClass.__init__(self) called
Addressing a comment
Why in the world would this be useful?
Python linearizes a complicated inheritance tree via the C3 linearization algorithm to create a Method Resolution Order (MRO).
We want methods to be looked up in that order.
For a method defined in a parent to find the next one in that order without super, it would have to
get the mro from the instance's type
look for the type that defines the method
find the next type with the method
bind that method and call it with the expected arguments
The UnsuperChild should not have access to InjectMe. Why isn't the conclusion "Always avoid using super"? What am I missing here?
The UnsuperChild does not have access to InjectMe. It is the UnsuperInjector that has access to InjectMe - and yet cannot call that class's method from the method it inherits from UnsuperChild.
Both Child classes intend to call a method by the same name that comes next in the MRO, which might be another class it was not aware of when it was created.
The one without super hard-codes its parent's method - thus is has restricted the behavior of its method, and subclasses cannot inject functionality in the call chain.
The one with super has greater flexibility. The call chain for the methods can be intercepted and functionality injected.
You may not need that functionality, but subclassers of your code may.
Conclusion
Always use super to reference the parent class instead of hard-coding it.
What you intend is to reference the parent class that is next-in-line, not specifically the one you see the child inheriting from.
Not using super can put unnecessary constraints on users of your code.
The benefits of super() in single-inheritance are minimal -- mostly, you don't have to hard-code the name of the base class into every method that uses its parent methods.
However, it's almost impossible to use multiple-inheritance without super(). This includes common idioms like mixins, interfaces, abstract classes, etc. This extends to code that later extends yours. If somebody later wanted to write a class that extended Child and a mixin, their code would not work properly.
I had played a bit with super(), and had recognized that we can change calling order.
For example, we have next hierarchy structure:
A
/ \
B C
\ /
D
In this case MRO of D will be (only for Python 3):
In [26]: D.__mro__
Out[26]: (__main__.D, __main__.B, __main__.C, __main__.A, object)
Let's create a class where super() calls after method execution.
In [23]: class A(object): # or with Python 3 can define class A:
...: def __init__(self):
...: print("I'm from A")
...:
...: class B(A):
...: def __init__(self):
...: print("I'm from B")
...: super().__init__()
...:
...: class C(A):
...: def __init__(self):
...: print("I'm from C")
...: super().__init__()
...:
...: class D(B, C):
...: def __init__(self):
...: print("I'm from D")
...: super().__init__()
...: d = D()
...:
I'm from D
I'm from B
I'm from C
I'm from A
A
/ ⇖
B ⇒ C
⇖ /
D
So we can see that resolution order is same as in MRO. But when we call super() in the beginning of the method:
In [21]: class A(object): # or class A:
...: def __init__(self):
...: print("I'm from A")
...:
...: class B(A):
...: def __init__(self):
...: super().__init__() # or super(B, self).__init_()
...: print("I'm from B")
...:
...: class C(A):
...: def __init__(self):
...: super().__init__()
...: print("I'm from C")
...:
...: class D(B, C):
...: def __init__(self):
...: super().__init__()
...: print("I'm from D")
...: d = D()
...:
I'm from A
I'm from C
I'm from B
I'm from D
We have a different order it is reversed a order of the MRO tuple.
A
/ ⇘
B ⇐ C
⇘ /
D
For additional reading I would recommend next answers:
C3 linearization example with super (a large hierarchy)
Important behavior changes between old and new style classes
The Inside Story on New-Style Classes
Doesn't all of this assume that the base class is a new-style class?
class A:
def __init__(self):
print("A.__init__()")
class B(A):
def __init__(self):
print("B.__init__()")
super(B, self).__init__()
Will not work in Python 2. class A must be new-style, i.e: class A(object)
When calling super() to resolve to a parent's version of a classmethod, instance method, or staticmethod, we want to pass the current class whose scope we are in as the first argument, to indicate which parent's scope we're trying to resolve to, and as a second argument the object of interest to indicate which object we're trying to apply that scope to.
Consider a class hierarchy A, B, and C where each class is the parent of the one following it, and a, b, and c respective instances of each.
super(B, b)
# resolves to the scope of B's parent i.e. A
# and applies that scope to b, as if b was an instance of A
super(C, c)
# resolves to the scope of C's parent i.e. B
# and applies that scope to c
super(B, c)
# resolves to the scope of B's parent i.e. A
# and applies that scope to c
Using super with a staticmethod
e.g. using super() from within the __new__() method
class A(object):
def __new__(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
return super(A, cls).__new__(cls, *a, **kw)
Explanation:
1- even though it's usual for __new__() to take as its first param a reference to the calling class, it is not implemented in Python as a classmethod, but rather a staticmethod. That is, a reference to a class has to be passed explicitly as the first argument when calling __new__() directly:
# if you defined this
class A(object):
def __new__(cls):
pass
# calling this would raise a TypeError due to the missing argument
A.__new__()
# whereas this would be fine
A.__new__(A)
2- when calling super() to get to the parent class we pass the child class A as its first argument, then we pass a reference to the object of interest, in this case it's the class reference that was passed when A.__new__(cls) was called. In most cases it also happens to be a reference to the child class. In some situations it might not be, for instance in the case of multiple generation inheritances.
super(A, cls)
3- since as a general rule __new__() is a staticmethod, super(A, cls).__new__ will also return a staticmethod and needs to be supplied all arguments explicitly, including the reference to the object of insterest, in this case cls.
super(A, cls).__new__(cls, *a, **kw)
4- doing the same thing without super
class A(object):
def __new__(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
return object.__new__(cls, *a, **kw)
Using super with an instance method
e.g. using super() from within __init__()
class A(object):
def __init__(self, *a, **kw):
# ...
# you make some changes here
# ...
super(A, self).__init__(*a, **kw)
Explanation:
1- __init__ is an instance method, meaning that it takes as its first argument a reference to an instance. When called directly from the instance, the reference is passed implicitly, that is you don't need to specify it:
# you try calling `__init__()` from the class without specifying an instance
# and a TypeError is raised due to the expected but missing reference
A.__init__() # TypeError ...
# you create an instance
a = A()
# you call `__init__()` from that instance and it works
a.__init__()
# you can also call `__init__()` with the class and explicitly pass the instance
A.__init__(a)
2- when calling super() within __init__() we pass the child class as the first argument and the object of interest as a second argument, which in general is a reference to an instance of the child class.
super(A, self)
3- The call super(A, self) returns a proxy that will resolve the scope and apply it to self as if it's now an instance of the parent class. Let's call that proxy s. Since __init__() is an instance method the call s.__init__(...) will implicitly pass a reference of self as the first argument to the parent's __init__().
4- to do the same without super we need to pass a reference to an instance explicitly to the parent's version of __init__().
class A(object):
def __init__(self, *a, **kw):
# ...
# you make some changes here
# ...
object.__init__(self, *a, **kw)
Using super with a classmethod
class A(object):
#classmethod
def alternate_constructor(cls, *a, **kw):
print "A.alternate_constructor called"
return cls(*a, **kw)
class B(A):
#classmethod
def alternate_constructor(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
print "B.alternate_constructor called"
return super(B, cls).alternate_constructor(*a, **kw)
Explanation:
1- A classmethod can be called from the class directly and takes as its first parameter a reference to the class.
# calling directly from the class is fine,
# a reference to the class is passed implicitly
a = A.alternate_constructor()
b = B.alternate_constructor()
2- when calling super() within a classmethod to resolve to its parent's version of it, we want to pass the current child class as the first argument to indicate which parent's scope we're trying to resolve to, and the object of interest as the second argument to indicate which object we want to apply that scope to, which in general is a reference to the child class itself or one of its subclasses.
super(B, cls_or_subcls)
3- The call super(B, cls) resolves to the scope of A and applies it to cls. Since alternate_constructor() is a classmethod the call super(B, cls).alternate_constructor(...) will implicitly pass a reference of cls as the first argument to A's version of alternate_constructor()
super(B, cls).alternate_constructor()
4- to do the same without using super() you would need to get a reference to the unbound version of A.alternate_constructor() (i.e. the explicit version of the function). Simply doing this would not work:
class B(A):
#classmethod
def alternate_constructor(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
print "B.alternate_constructor called"
return A.alternate_constructor(cls, *a, **kw)
The above would not work because the A.alternate_constructor() method takes an implicit reference to A as its first argument. The cls being passed here would be its second argument.
class B(A):
#classmethod
def alternate_constructor(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
print "B.alternate_constructor called"
# first we get a reference to the unbound
# `A.alternate_constructor` function
unbound_func = A.alternate_constructor.im_func
# now we call it and pass our own `cls` as its first argument
return unbound_func(cls, *a, **kw)
Super() in a nutshell
Every Python instance has a class that created it.
Every class in Python has a chain of ancestor classes.
A method using super() delegates work to the next ancestor in the chain for the instance's class.
Example
This small example covers all the interesting cases:
class A:
def m(self):
print('A')
class B(A):
def m(self):
print('B start')
super().m()
print('B end')
class C(A):
def m(self):
print('C start')
super().m()
print('C end')
class D(B, C):
def m(self):
print('D start')
super().m()
print('D end')
The exact order of calls is determined by the instance the method is called from:
>>> a = A()
>>> b = B()
>>> c = C()
>>> d = D()
For instance a, there is no super call:
>>> a.m()
A
For instance b, the ancestor chain is B -> A -> object:
>>> type(b).__mro__
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
>>> b.m()
B start
A
B end
For instance c, the ancestor chain is C -> A -> object:
>>> type(c).__mro__
(<class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
>>> c.m()
C start
A
C end
For instance d, the ancestor chain is more interesting D -> B -> C -> A -> object (mro stands for method resolution order) :
>>> type(d).__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
>>> d.m()
D start
B start
C start
A
C end
B end
D end
More information
Having answered the question of "What does super do in Python?", the next question is how to use it effectively. See this step-by-step tutorial or this 45 minute video.
Many great answers, but for visual learners:
Firstly lets explore with arguments to super, and then without.
Imagine theres an instance jack created from the class Jack, who has the inheritance chain as shown in green in the picture. Calling:
super(Jack, jack).method(...)
will use the MRO (Method Resolution Order) of jack (its inheritance tree in a certain order), and will start searching from Jack. Why can one provide a parent class? Well if we start searching from the instance jack, it would find the instance method, the whole point is to find its parents method.
If one does not supply arguments to super, its like the first argument passed in is the class of self, and the second argument passed in is self. These are auto-calculated for you in Python3.
However say we dont want to use Jack's method, instead of passing in Jack, we could of passed in Jen to start searching upwards for the method from Jen.
It searches one layer at a time (width not depth), e.g. if Adam and Sue both have the required method, the one from Sue will be found first.
If Cain and Sue both had the required method, Cain's method would be called first.
This corresponds in code to:
Class Jen(Cain, Sue):
MRO is from left to right.
In the case of multiple inheritance, you normally want to call the initializers of both parents, not just the first. Instead of always using the base class, super() finds the class that is next in Method Resolution Order (MRO), and returns the current object as an instance of that class. For example:
class Base(object):
def __init__(self):
print("initializing Base")
class ChildA(Base):
def __init__(self):
print("initializing ChildA")
Base.__init__(self)
class ChildB(Base):
def __init__(self):
print("initializing ChildB")
super().__init__()
class Grandchild(ChildA, ChildB):
def __init__(self):
print("initializing Grandchild")
super().__init__()
Grandchild()
results in
initializing Grandchild
initializing ChildA
initializing Base
Replacing Base.__init__(self) with super().__init__() results in
initializing Grandchild
initializing ChildA
initializing ChildB
initializing Base
as desired.
some great answers here, but they do not tackle how to use super() in the case where different classes in the hierarchy have different signatures ... especially in the case of __init__
to answer that part and to be able to effectively use super() i'd suggest reading my answer super() and changing the signature of cooperative methods.
here's just the solution to this scenario:
the top-level classes in your hierarchy must inherit from a custom class like SuperObject:
if classes can take differing arguments, always pass all arguments you received on to the super function as keyword arguments, and, always accept **kwargs.
class SuperObject:
def __init__(self, **kwargs):
print('SuperObject')
mro = type(self).__mro__
assert mro[-1] is object
if mro[-2] is not SuperObject:
raise TypeError(
'all top-level classes in this hierarchy must inherit from SuperObject',
'the last class in the MRO should be SuperObject',
f'mro={[cls.__name__ for cls in mro]}'
)
# super().__init__ is guaranteed to be object.__init__
init = super().__init__
init()
example usage:
class A(SuperObject):
def __init__(self, **kwargs):
print("A")
super(A, self).__init__(**kwargs)
class B(SuperObject):
def __init__(self, **kwargs):
print("B")
super(B, self).__init__(**kwargs)
class C(A):
def __init__(self, age, **kwargs):
print("C",f"age={age}")
super(C, self).__init__(age=age, **kwargs)
class D(B):
def __init__(self, name, **kwargs):
print("D", f"name={name}")
super(D, self).__init__(name=name, **kwargs)
class E(C,D):
def __init__(self, name, age, *args, **kwargs):
print( "E", f"name={name}", f"age={age}")
super(E, self).__init__(name=name, age=age, *args, **kwargs)
E(name='python', age=28)
output:
E name=python age=28
C age=28
A
D name=python
B
SuperObject
Consider the following code:
class X():
def __init__(self):
print("X")
class Y(X):
def __init__(self):
# X.__init__(self)
super(Y, self).__init__()
print("Y")
class P(X):
def __init__(self):
super(P, self).__init__()
print("P")
class Q(Y, P):
def __init__(self):
super(Q, self).__init__()
print("Q")
Q()
If change constructor of Y to X.__init__, you will get:
X
Y
Q
But using super(Y, self).__init__(), you will get:
X
P
Y
Q
And P or Q may even be involved from another file which you don't know when you writing X and Y. So, basically, you won't know what super(Child, self) will reference to when you are writing class Y(X), even the signature of Y is as simple as Y(X). That's why super could be a better choice.
class Child(SomeBaseClass):
def __init__(self):
SomeBaseClass.__init__(self)
This is fairly easy to understand.
class Child(SomeBaseClass):
def __init__(self):
super(Child, self).__init__()
Ok, what happens now if you use super(Child,self)?
When a Child instance is created, its MRO(Method Resolution Order) is in the order of (Child, SomeBaseClass, object) based on the inheritance. (assume SomeBaseClass doesn't have other parents except for the default object)
By passing Child, self, super searches in the MRO of the self instance, and return the proxy object next of Child, in this case it's SomeBaseClass, this object then invokes the __init__ method of SomeBaseClass. In other word, if it's super(SomeBaseClass,self), the proxy object that super returns would be object
For multi inheritance, the MRO could contain many classes, so basically super lets you decide where you want to start searching in the MRO.
Is there a reasonable way in Python to implement mixin behavior similar to that found in Ruby -- that is, without using inheritance?
class Mixin(object):
def b(self): print "b()"
def c(self): print "c()"
class Foo(object):
# Somehow mix in the behavior of the Mixin class,
# so that all of the methods below will run and
# the issubclass() test will be False.
def a(self): print "a()"
f = Foo()
f.a()
f.b()
f.c()
print issubclass(Foo, Mixin)
I had a vague idea to do this with a class decorator, but my attempts led to confusion. Most of my searches on the topic have led in the direction of using inheritance (or in more complex scenarios, multiple inheritance) to achieve mixin behavior.
def mixer(*args):
"""Decorator for mixing mixins"""
def inner(cls):
for a,k in ((a,k) for a in args for k,v in vars(a).items() if callable(v)):
setattr(cls, k, getattr(a, k).im_func)
return cls
return inner
class Mixin(object):
def b(self): print "b()"
def c(self): print "c()"
class Mixin2(object):
def d(self): print "d()"
def e(self): print "e()"
#mixer(Mixin, Mixin2)
class Foo(object):
# Somehow mix in the behavior of the Mixin class,
# so that all of the methods below will run and
# the issubclass() test will be False.
def a(self): print "a()"
f = Foo()
f.a()
f.b()
f.c()
f.d()
f.e()
print issubclass(Foo, Mixin)
output:
a()
b()
c()
d()
e()
False
You can add the methods as functions:
Foo.b = Mixin.b.im_func
Foo.c = Mixin.c.im_func
I am not that familiar with Python, but from what I know about Python metaprogramming, you could actually do it pretty much the same way it is done in Ruby.
In Ruby, a module basically consists of two things: a pointer to a method dictionary and a pointer to a constant dictionary. A class consists of three things: a pointer to a method dictionary, a pointer to a constant dictionary and a pointer to the superclass.
When you mix in a module M into a class C, the following happens:
an anonymous class α is created (this is called an include class)
α's method dictionary and constant dictionary pointers are set equal to M's
α's superclass pointer is set equal to C's
C's superclass pointer is set to α
In other words: a fake class which shares its behavior with the mixin is injected into the inheritance hierarchy. So, Ruby actually does use inheritance for mixin composition.
I left out a couple of subleties above: first off, the module doesn't actually get inserted as C's superclass, it gets inserted as C's superclasses' (which is C's singleton class) superclass. And secondly, if the mixin itself has mixed in other mixins, then those also get wrapped into fake classes which get inserted directly above α, and this process is applied recursively, in case the mixed in mixins in turn have mixins.
Basically, the whole mixin hierarchy gets flattened into a straight line and spliced into the inheritance chain.
AFAIK, Python actually allows you to change a class's superclass(es) after the fact (something which Ruby does not allow you to do), and it also gives you access to a class's dict (again, something that is impossible in Ruby), so you should be able to implement this yourself.
EDIT: Fixed what could (and probably should) be construed as a bug. Now it builds a new dict and then updates that from the class's dict. This prevents mixins from overwriting methods that are defined directly on the class. The code is still untested but should work. I'm busy ATM so I'll test it later. It worked fine except for a syntax error. In retrospect, I decided that I don't like it (even after my further improvements) and much prefer my other solution even if it is more complicated. The test code for that one applies here as well but I wont duplicate it.
You could use a metaclass factory:
import inspect
def add_mixins(*mixins):
Dummy = type('Dummy', mixins, {})
d = {}
for mixin in reversed(inspect.getmro(Dummy)):
d.update(mixin.__dict__)
class WithMixins(type):
def __new__(meta, classname, bases, classdict):
d.update(classdict)
return super(WithMixins, meta).__new__(meta, classname, bases, d)
return WithMixins
then use it like:
class Foo(object):
__metaclass__ = add_mixins(Mixin1, Mixin2)
# rest of the stuff
This one is based on the way it's done in ruby as explained by Jörg W Mittag. All of the wall of code after if __name__=='__main__' is test/demo code. There's actually only 13 lines of real code to it.
import inspect
def add_mixins(*mixins):
Dummy = type('Dummy', mixins, {})
d = {}
# Now get all the class attributes. Use reversed so that conflicts
# are resolved with the proper priority. This rules out the possibility
# of the mixins calling methods from their base classes that get overridden
# using super but is necessary for the subclass check to fail. If that wasn't a
# requirement, we would just use Dummy above (or use MI directly and
# forget all the metaclass stuff).
for base in reversed(inspect.getmro(Dummy)):
d.update(base.__dict__)
# Create the mixin class. This should be equivalent to creating the
# anonymous class in Ruby.
Mixin = type('Mixin', (object,), d)
class WithMixins(type):
def __new__(meta, classname, bases, classdict):
# The check below prevents an inheritance cycle from forming which
# leads to a TypeError when trying to inherit from the resulting
# class.
if not any(issubclass(base, Mixin) for base in bases):
# This should be the the equivalent of setting the superclass
# pointers in Ruby.
bases = (Mixin,) + bases
return super(WithMixins, meta).__new__(meta, classname, bases,
classdict)
return WithMixins
if __name__ == '__main__':
class Mixin1(object):
def b(self): print "b()"
def c(self): print "c()"
class Mixin2(object):
def d(self): print "d()"
def e(self): print "e()"
class Mixin3Base(object):
def f(self): print "f()"
class Mixin3(Mixin3Base): pass
class Foo(object):
__metaclass__ = add_mixins(Mixin1, Mixin2, Mixin3)
def a(self): print "a()"
class Bar(Foo):
def f(self): print "Bar.f()"
def test_class(cls):
print "Testing {0}".format(cls.__name__)
f = cls()
f.a()
f.b()
f.c()
f.d()
f.e()
f.f()
print (issubclass(cls, Mixin1) or
issubclass(cls, Mixin2) or
issubclass(cls, Mixin3))
test_class(Foo)
test_class(Bar)
You could decorate the classes __getattr__ to check in the mixin. The problem is that all methods of the mixin would always require an object the type of the mixin as their first parameter, so you would have to decorate __init__ as well to create a mixin-object. I believe you could achieve this using a class decorator.
from functools import partial
class Mixin(object):
#staticmethod
def b(self): print "b()"
#staticmethod
def c(self): print "c()"
class Foo(object):
def __init__(self, mixin_cls):
self.delegate_cls = mixin_cls
def __getattr__(self, attr):
if hasattr(self.delegate_cls, attr):
return partial(getattr(self.delegate_cls, attr), self)
def a(self): print "a()"
f = Foo(Mixin)
f.a()
f.b()
f.c()
print issubclass(Foo, Mixin)
This basically uses the Mixin class as a container to hold ad-hoc functions (not methods) that behave like methods by taking an object instance (self) as the first argument. __getattr__ will redirect missing calls to these methods-alike functions.
This passes your simple tests as shown below. But I cannot guarantee it will do all the things you want. Make more thorough test to make sure.
$ python mixin.py
a()
b()
c()
False
Composition? It seems like that would be the simplest way to handle this: either wrap your object in a decorator or just import the methods as an object into your class definition itself. This is what I usually do: put the methods that I want to share between classes in a file and then import the file. If I want to override some behavior I import a modified file with the same method names as the same object name. It's a little sloppy, but it works.
For example, if I want the init_covers behavior from this file (bedg.py)
import cove as cov
def init_covers(n):
n.covers.append(cov.Cover((set([n.id]))))
id_list = []
for a in n.neighbors:
id_list.append(a.id)
n.covers.append(cov.Cover((set(id_list))))
def update_degree(n):
for a in n.covers:
a.degree = 0
for b in n.covers:
if a != b:
a.degree += len(a.node_list.intersection(b.node_list))
In my bar class file I would do: import bedg as foo
and then if I want to change my foo behaviors in another class that inherited bar, I write
import bild as foo
Like I say, it is sloppy.