PEP 266: Optimizing Global Variable/Attribute Access

Greg Ball greg.ball at earthling.net
Wed Aug 15 18:16:49 CEST 2001


"Alex Martelli" <aleaxit at yahoo.com> wrote in message news:<9ldakm01ioq at enews3.newsguy.com>...
> So, if Python's dynamic semantics are to stay untouched, any
> caching or hoisting of method resolution MUST track potential
> modifications.  Of course, the antecedent of this hypothetical
> sentence is pretty iffy -- but, one COULD construct a case.


Speaking of caching of method resolution... 

I've been thinking about the discussion of how valuable assignment to
__class__ is.  I've thought about several examples presented and I
agree that it is a concise and elegant way to solve the problem of
object state.

However, I have realised that there is a fly in the ointment.
Namely, bound methods.  An object choosing to change its class means
that it wishes to change its behaviour.  However, if somewhere a
client has already obtained a bound method (which is after all, a
first class object, so the client can hardly be upbraided for this?)
then the old behaviour is hiding in that one method, ready to create
some potentially interesting effects...

As an example I'll take the unique case in current python where a
built in object changes it's type.

Here's the way it's supposed to work:

Python 2.2a1 (#16, Aug  4 2001, 12:44:54) 
[GCC 2.95.3 19991030 (prerelease)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class C:
...     def __cmp__(self,other):
...             gl.pop()
...             return 0
... 
>>> gl = [C() for i in range(20)]
>>> gl.sort()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 3, in __cmp__
AttributeError: 'list (immutable, during sort)' object has no
attribute 'pop'
>>>


But it can also work like this:

>>> class C:
...     def __cmp__(self,other):
...             pop()
...             return 0
... 
>>> gl = [C() for i in range(20)]
>>> pop=gl.pop
>>> gl.sort()
Segmentation fault (core dumped)

By binding a method from <type 'list'> and holding onto it, I get
around the fact that the object wanted to change it's behaviour.  Now
I admit that this particular case is deliberate mischief making. 
However, I think you would agree that *if* a given objects __class__
is subject to change, I would be well advised not to hold onto any
bound methods of that object.  More, if I am to be conservative, I
need to assume that this might happen to *any* object of a class the
implementation of which I have not studied - which applies to almost
any object at all, if I write my code with pure signature-based
polymorphism.  Therefore, caching bound methods must be considered
risky, if class changing behaviour is considered acceptable.

To avoid this problem while allowing class reassignment, my guess is
that a bound method object would need to store not only the underlying
function and the relevant instance, but also the type of the instance
at the time of binding.  It could then do a last minute type check at
the time that the method is called.
In other words, the solution is to add another runtime type check, or
to summarise the summary, current python is *not* sufficiently
dynamic!

This suggestion is pretty impractical however since it adds a space
and time overhead to every bound method call, and I know these calls
are very, very common (including almost** every arithmetic operation
as well as explicit method calls).  Of course the typical

instance.method(arg)

pattern on a class instance has a pretty high overhead right now,
especially if the method is found deep down the class heirarchy, but
that is one of the chief targets for improved performance in the new
scheme of things I imagine, so there will be reluctance to add a new
burden to the operation.

On the other hand Tim Peters *does* seem to be enamoured with the
immutable list trick, so maybe he will be tempted to make it more
bulletproof.

** almost, meaning except for integer operations handcoded in the
eval_code2
loop, as far as I know.

--
Greg



More information about the Python-list mailing list