Coming from a Perl background, I'm used to something like:
my @words = qw(fee fi fo fum);
I'm wondering if the following Python incurs a run-time performance hit:
words = 'fee fi fo fum'.split()
or if words
is bound at compile-time.
Compile time is the period when the programming code (such as C#, Java, C, Python) is converted to the machine code (i.e. binary code). Runtime is the period of time when a program is running and generally occurs after compile time.
In computing, compile-time function execution (or compile time function evaluation, or general constant expressions) is the ability of a compiler, that would normally compile a function to machine code and execute it at run time, to execute the function at compile time.
Compile-time is the time at which the source code is converted into an executable code while the run time is the time at which the executable code is started running. Both the compile-time and runtime refer to different types of error.
In computer science, compile time (or compile-time) describes the time window during which a computer program is compiled. The term is used as an adjective to describe concepts related to the context of program compilation, as opposed to concepts related to the context of program execution (runtime).
You can view bytecode using the dis
module:
>>> from dis import dis
>>>
>>> def f():
... words = 'fee fi fo fum'.split()
...
>>> dis(f)
2 0 LOAD_CONST 1 ('fee fi fo fum')
3 LOAD_ATTR 0 (split)
6 CALL_FUNCTION 0
9 STORE_FAST 0 (words)
12 LOAD_CONST 0 (None)
15 RETURN_VALUE
split
(as loaded by LOAD_ATTR
) is called via CALL_FUNCTION
and its result is assigned to words
via STORE_FAST
at runtime. In other words, x.split()
is not resolved at compile-time, even if x
is a hardcoded string.
Of course, the performance difference between using 'fee fi fo fum'.split()
and its result, namely ['fee', 'fi', 'fo', 'fum']
, is going to be negligible, so don't change from one to the other only for the sake of a performance boost.
Not even in PERL it can be bound at compile time because every time you get through that statement a new fresh list must be created.
In other words in Python when you see
x = ['fee', 'fi', 'fo', 'fum']
the code cannot just load a specific object address into x
because it must be a new fresh list object each time you get on the statement. Consider
def foo():
return ['fee', 'fi', 'fo', 'fum']
x = foo()
x[0] = 'bar'
print foo()[0] # must be 'fee'
print x[0] # must be 'bar'
Python however does some optimization for immutables; for example:
def foo():
return (1, 2, 3)
actually always return the very same object (it doesn't allocate a new tuple each time), and for
def foo():
return 3 * 4
it actually returns 12 without making the multiplication at runtime.
Your example however cannot be resolved to loading a constant computed at compile time, it must be at least a list "literal" (that is indeed a list generator creating a new object each time is evaluated).
IIRC constant folding is only done at compile time for binary operators on number/strings and not for any function call (note that in Python it's legal, even if bad practice, to change for example the standard function len
, so you cannot be sure that len("foo")
always returns 3).
Calls of methods on standard strings passing only constants could indeed IMO be moved at compile time, but AFAIK it's not done at this moment (and it's not common, so may be the gain is not worth the effort).
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