Speed Static Methods vs Class Method
Asked Answered
P

1

14

Is there any speed difference between class Methods and Static Methods? I am aware of the different use cases, but sometimes i could completely get rid of a class method and would like to know speed differences

Pica answered 26/5, 2016 at 23:5 Comment(0)
W
22

Test it. This is going to be an implementation detail of whichever Python interpreter (and version of said interpreter) you happen to be running. For my interpreter (Python 3.5, Windows, 64 bit):

>>> class Foo:
...     @classmethod
...     def bar(cls):
...         pass
...     @staticmethod
...     def baz():
...         pass
...
>>> import timeit
>>> min(timeit.repeat('Foo.bar()', 'from __main__ import Foo', repeat=5, number=100000))
0.02093224880448102
>>> min(timeit.repeat('Foo.baz()', 'from __main__ import Foo', repeat=5, number=100000))
0.017951558014670965
>>> min(timeit.repeat('f.bar()', 'from __main__ import Foo; f = Foo()', repeat=5, number=100000))
0.020720195652103257
>>> min(timeit.repeat('f.baz()', 'from __main__ import Foo; f = Foo()', repeat=5, number=100000))
0.017714758216740734

It looks like staticmethod is slightly faster (likely just because it doesn't need to pass an argument into the function at all), but we're talking about a difference of 3 milliseconds for 100,000 calls, which is nanoseconds per call in cost.

Worsham answered 26/5, 2016 at 23:13 Comment(7)
Just ran the same tests... 104 ns for static, 115 ns for not static.Dartmouth
The fact that static methods would be faster seems intuitive. I'm not sure the underlying mechanisms in Python, but if its anything like C++ there's a number additional steps involved in calling a function using an object when compared to a static function.Poole
@DrewBuckley: Those steps aren't skipped in Python (lookup in Python is always dynamic lookup, it's just a matter of which dictionaries get searched). You'll notice it's actually ever so slightly faster calling the static or class method on an instance of the class than on the class object itself; that may be a timing artifact, but it's clear than there is no optimization when calling on the class itself.Worsham
Follow up to "it's actually ever so slightly faster calling the static or class method on an instance of the class than on the class object itself". This is an artifact of how lookup is performed. To enable the descriptor protocol, attributes are always looked up on class first, then instance. So when you look it up on an instance of the class, it goes directly to the class and finds the method. When you look it up on the class, it checks the metaclass first. For a non-trivial metaclass, this might introduce real overhead, but for the trivial metaclass, type, it's only barely detectable.Worsham
I'd like to see this same test with more methods, both static and class. There may be a cost to object creation which is not taken into account by this simple test.Allimportant
@AdamOutler: You mean creating an object solely for the purpose of calling a classmethod or staticmethod on it? Yeah, that would definitely outweigh any savings from it being cheaper to call it on an instance. Constructing even trivial instances of a user-defined class with no user-defined __init__ or __new__ costs roughly twice the incremental overhead of calling the method on the class rather than the instance. The performance benefits only apply when you have a choice, e.g. when you're in another method and can do ClassName.meth() or self.meth(). There are style arguments in...Worsham
...of the latter, and it turns out performance supports that choice as well (for multiple reasons; my benchmarks intentionally made the class and instance locals, so lookup costs were minimal; normally, ClassName would be a global lookup, while self is almost definitionally local, and while they've optimized global lookups a lot in modern Python, it's always going to be a little slower).Worsham

© 2022 - 2024 — McMap. All rights reserved.