Knowing that calling a function in python is expensive, the answer to this question has some bearing on optimization decisions, e.g. in comparing a straight one-function numeric approach to an object-oriented one. So I'd like to know
My google-fu was not up to the task of finding an answer to this question.
EDIT: So to summarize the comments and forestall more close votes, here's some clarifications:
To create instances of a class, you call the class using class name and pass in whatever arguments its __init__ method accepts.
To call a predefined static function, simply type the class name followed by a dot and a function name. To call a user-defined or predefined non-static java function, create a class object and then follow the dot “.” syntax to call the function.
Functions do specific things, classes are specific things. Classes often have methods, which are functions that are associated with a particular class, and do things associated with the thing that the class is - but if all you want is to do something, a function is all you need.
In Python, functions behave like any other object, such as an int or a list. That means that you can use functions as arguments to other functions, store functions as dictionary values, or return a function from another function.
See Python Object Creation by Eli Bendersky.
Quoting at length the conclusion:
Lest we lose the forest for the trees, let’s revisit the question this article began with. What happens when CPython executes
j = Joe()?
- Since
Joehas no explicit metaclass,typeis its type. So thetp_callslot oftype, which istype_call, is called.type_callstarts by calling thetp_newslot of Joe:
- Since Joe has no explicit base clase, its base is
object. Therefore,object_newis called.- Since Joe is a Python-defined class, it has no custom
tp_allocslot. Therefore,object_newcallsPyType_GenericAlloc.PyType_GenericAllocallocates and initializes a chunk of memory big enough to contain Joe.type_callthen goes on and callsJoe.__init__on the newly created object.
- Since
Joedoes not define__init__, its base’s__init__is called, which isobject_init.object_initdoes nothing.- The new object is returned from
type_calland is bound to the namej.
I've done as suggested in the comments and used timeit on these test cases:
def a():
pass
class A(object):
pass
class B(object):
def __init__(self):
pass
class NOPType(type):
pass
class C(object):
__metaclass__ = NOPType
def __init__(self):
pass
class D(object):
def __new__(cls, *args, **kwargs):
return super(D, cls).__new__(cls)
def __init__(self):
pass
class E(A):
def __init__(self):
super(E, self).__init__()
Test results:
$ python -m timeit -s "import tst" "tst.a()" 10000000 loops, best of 3: 0.149 usec per loop $ python -m timeit -s "import tst" "tst.A()" 10000000 loops, best of 3: 0.169 usec per loop $ python -m timeit -s "import tst" "tst.B()" 1000000 loops, best of 3: 0.384 usec per loop $ python -m timeit -s "import tst" "tst.C()" 1000000 loops, best of 3: 0.397 usec per loop $ python -m timeit -s "import tst" "tst.D()" 1000000 loops, best of 3: 1.09 usec per loop $ python -m timeit -s "import tst" "tst.E()" 1000000 loops, best of 3: 0.827 usec per loop
Using a function call as a baseline, these are the results:
__init__ method increases the factor to 2.6__new__, it's equivalent to 7.3 function callsFor the last two result you can subtract about 2 if the call to super is replaced with its return value.
This should give a rough estimate of how time-expensive python classes are compared to python functions, in CPython 2.7.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With