The Cost of Dynamism (was Re: Pyhon 2.x or 3.x, which is faster?)

Marko Rauhamaa marko at pacujo.net
Sat Mar 12 09:38:38 EST 2016


BartC <bc at freeuk.com>:

> Ad-hoc attributes I don't have as much of a problem with, as they can
> be handy. But predefined ones also have their points. (For one thing,
> I know how to implement those efficiently.)

I wonder how large a proportion of all references are top-level. My
hunch is that it is well below 10% in a normal Python program.

> However, when you have a function call like this: M.F(), where M is an
> imported module, then it is very unlikely that the functions in M are
> going to be created, modified, deleted or replaced while the program
> runs. [I mean, after the usual process of executing each 'def'
> statement.]

There M is top-level, M.F is a level below. Even adjusting for the
meaning of "top-level," most accesses in a typical Python program are
attribute references due to object orientation.

> Why then should it have to suffer the same overheads as looking up
> arbitrary attributes? And on every single call?

It doesn't much matter because the "top level" probably plays an
insignificant role in the performance.

>> I also have a high level of method/attribute transparency. It doesn't
>> matter if I declare:
>>
>>         def this_or_that(self):
>>             if self.that:
>>                 self.that()
>>             else:
>>                 self.this()
>>
>>         [...]
>>
>>             self.that = True
>>
>> or:
>>
>>             self.this_or_that = self.that
>
> This example, I don't understand. Do you mean that when your write X.Y,
> that Y can be an attribute of X one minute, and a method the next? (In
> which case I wouldn't want to have to maintain your code!)

What I wanted to say above is that I have a choice of implementing a
dynamic method using attribute assignment or a method definition. For
all practical purposes, an object method is an attribute. You can write
it using the handy "def" syntax or you can use an assignment.

Python has defined it in a slightly more convoluted manner, but you
would almost never sense the difference. Here's a whiff of the
convolution:

   >>> four = 4
   >>> four.__str__ is four.__str__

What happens here is that Python first sees if the builtin object 4 has
an attribute named "__str__". It doesn't. Python then proceeds to 4's
class, int, and finds int.__str__, which is the underlying method in the
class. Python then constructs a delegate function like this:

    lambda *x, **y: int.__str__(4, *x, **y)

and returns it.

>> Somewhat related, every method is an automatic delegate. Defining
>> callbacks is a breeze:
>>
>>         def clickety_click(self, x, y):
>>             [...]
>>
>>         [...]
>>             window.register_mouse_click_callback(self.clickety_click)
>
> I don't follow this either. What's the advantage of dynamism here?

Dynamism doesn't play a direct role here, but the convolution I describe
above makes the magic possible.

(There would be a less convoluted way to come up with almost identical
semantics, but that would cost memory and object instantiation time.)


Marko



More information about the Python-list mailing list