Assuming you really need the speed, the only savings to be gained (in CPython) is to reduce the amount of bytecode you're executing, and even storing to locals costs additional byte code work (even if it doesn't do much work for each byte code instruction, simply working through them has overhead). So basically, minimize intermediate storage (and therefore byte codes) by one-lining it as in your commented out code (although on really old Python, you'd need a tuple
of constants for the not in
check to avoid Python stupidly reconstructing a list
each time):
def _epoch_to_dinfo(epoch):
return (epoch // 86400) % 7 not in (2, 3), (epoch % 86400) // 60
Just by one-lining, the cost per run in my Python 2.7 x86 install drops by ~23%.
You might think you'd be able to use divmod
to calculate the quotient and remainder of epoch divided by 86400 at once, but the cost of looking up divmod
from the builtin namespace (expensive thanks to LEGB search), calling it (substantially more expensive than syntax based calls like //
and %
), unpacking its results, and loading the unpacked results back from the stack mean it ends up costing substantially more than even the non-one-lined solution; unless the inputs are large enough that the actual math work done outweighs the lookup costs and function call overhead significantly (which usually means the numbers have to be large enough to invoke array based math and then some; using long
in Py2, or int
s that exceed the digit
size, 15 or 30 bits for 32 and 64 bit systems, in Py3), divmod
almost never saves time.
Similarly, the test of not in (2, 3)
wins over all other approaches, not because it's logically faster, but because it simplifies to LOAD_CONST
of the constant tuple
and invoking COMPARE_OP
for not in
(after which the comparisons are done at the C layer); individual tests against 2 and 3 would load more constants, invoke more COMPARE_OP
s and do conditional jumps and such in Python byte code and that's more expensive.
None of this advice applies to any interpreter besides CPython (and much of it might only apply to CPython 2.7), because it's all implementation details.