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
Joe
has no explicit metaclass,type
is its type. So thetp_call
slot oftype
, which istype_call
, is called.type_call
starts by calling thetp_new
slot of Joe:
- Since Joe has no explicit base clase, its base is
object
. Therefore,object_new
is called.- Since Joe is a Python-defined class, it has no custom
tp_alloc
slot. Therefore,object_new
callsPyType_GenericAlloc
.PyType_GenericAlloc
allocates and initializes a chunk of memory big enough to contain Joe.type_call
then goes on and callsJoe.__init__
on the newly created object.
- Since
Joe
does not define__init__
, its base’s__init__
is called, which isobject_init
.object_init
does nothing.- The new object is returned from
type_call
and 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