On Tue, Oct 12, 2021 at 06:34:06AM -0000, Jeremiah Vivian wrote:
So `ord` is already a really fast function with (last check before this thread was posted) 166 nsec per loop. But I'm wondering... doing `ord(a)` produces this bytecode:
2 4 LOAD_NAME 1 (ord) 6 LOAD_NAME 0 (a) 8 CALL_FUNCTION 1 10 POP_TOP 12 LOAD_CONST 1 (None) 14 RETURN_VALUE
But doing `+a` only produces this:
2 4 LOAD_NAME 0 (a) 6 UNARY_POSITIVE 8 POP_TOP 10 LOAD_CONST 1 (None) 12 RETURN_VALUE
Don't be fooled though, the UNARY_POSITIVE byte-code has to inspect the argument `a` for a `__pos__` method, and if it exists, call it. So there is a couple of hidden function calls in there.
But it is true that operators do save the cost of looking up the function name.
So an operator has its own bytecode, doesn't need to `LOAD_*` a function, and doesn't have the impact on performance when converting arguments to the format of the (after `POP()`ing every argument) TOS function and then calling that function.
If the lookup of a function is having a significant cost to you, perhaps because you are calling the function in a really tight loop, there is an optimization you can do. Suppose we have an enormous string with a billion characters, and we run this:
a = 0 for c in enormous_string: a += ord(c)
That looks up ord once for every character in the string. But if we move the code to a function, and use a local variable, we can reduce those lookups to one instead of a billion:
def func(enormous_string): ordinal = ord a = 0 for c in enormous_string: a += ordinal(c) return a
a = func(enormous_string)
That may give you a small percentage boost.
And also, the unary `+` of strings only copies strings, which should be redundant in most cases.
Are you sure about that?
>>> s = +"a" Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: bad operand type for unary +: 'str'
I don't think it works. What version of Python are you using?