The Cost of Dynamism (was Re: Pyhon 2.x or 3.x, which is faster?)
BartC
bc at freeuk.com
Sun Mar 13 09:16:39 EDT 2016
On 13/03/2016 09:39, Steven D'Aprano wrote:
> On Sun, 13 Mar 2016 04:54 am, BartC wrote:
>> Common sense tells you it is unlikely.
>
> Perhaps your common sense is different from other people's common sense. To
> me, and many other Python programmers, it's common sense that being able to
> replace functions or methods on the fly is a useful feature worth having.
Worth having but at significant cost. But look at my jpeg test (look at
any other similar programs); how many function names are used
dynamically? How many functions *really* need to be dynamic?
>> (Have you tried looking at the CPython sources?
> Right. Now add *on top of that complexity* the extra complexity needed to
> manage not one, but *two* namespaces for every scope: one for "variables"
> and one for "functions and methods".
No, there's one namespace per scope. (Otherwise you could have a
function 'f' and a variable 'f' in each scope.)
Perhaps what you mean is the number of different kinds of identifiers
there can be. At the minute, apart from obvious, fixed, reserved words
(I assume there are some!), there seems to be just one kind. The
different categories (function, variable, class, built-in, module etc)
are sorted out at *run-time*.
Some of this will just move to *compile-time*. Same amount of
complexity, but now you do it just once at compile-time, instead of a
billion times at run-time.
>> def f(): return "One"
>> def g(): return "Two"
>>
>> h=f
> Let me see if I can draw you a more complete picture. Suppose I have a
> function that relies on (let's say) something random or unpredictable:
>
> def get_data():
> return time.strftime("%S:%H")
> Now I use `get_data` in another function:
>
> def spam():
> value = get_stuff().replace(":", "")
(I assume you mean get_data here.)
> How do I test the `spam` function? I cannot easily predict what the
> `get_data` function will return.
>
> In Python, I can easily monkey-patch this for the purposes of testing, or
> debugging, by introducing a test double (think of "stunt double") to
> replace the real `get_data` function:
>
> import mymodule
> mymodule.get_data = lambda: "1:1"
> assert spam() == "Spam to the 11"
(How do you get back the original get_data?) But this looks a very
dangerous technique. Suppose, during the test, that another function in
mymodule, or one that imports it, needs access to the original get_data
function to work properly? Now it will get back nonsense.
> How would you do it, when functions are constant? You would have to re-write
> the module to allow it:
There are a dozen ways of doing it. It may involve temporary renaming or
hiding. But what you don't want is for production code to be lumbered
with all these lookups (and having to sort out arguments, keywords and
defaults) at runtime, just to make it a bit easier for debug code to run.
I think anyway that any Python program using dynamic functions, can be
trivially transformed to one that uses static functions. It won't be
pretty, but any function:
def f(): whatever
could be rewritten as:
def __f(): whatever
f = __f()
But now the static name __f is available for direct use, and can be
depended on not to change.
(Perhaps such a convention can be used anyway. A functions that starts
with "__" or uses some other device, the compiler and runtime will know
it will always be that function, and could allow some optimisations.)
(It's not quite so trivial for import module names, as you can't really
just rename all modules! But in theory it could be done.)
> I once monkey-patched the `len` built-in so I could monitor the progress of
> a long-running piece of code that wasn't written to give any feedback.
These ought to be tricks that you do with source code. It shouldn't be
necessary for an implementation to allow that.
(But doesn't len() already have a mechanism where you can override it
anyway?)
--
Bartc
More information about the Python-list
mailing list