[Python-Dev] PEP 447: add type.__locallookup__

Ronald Oussoren ronaldoussoren at mac.com
Thu Sep 19 11:32:17 CEST 2013

On 14 Sep, 2013, at 8:30, Nick Coghlan <ncoghlan at gmail.com> wrote:

[... interesting text that I'll respond to later ...]

> So my proposed name is based on the idea that what Ronald is after
> with the PEP is a hook that *only* gets invoked when the interpreter
> is doing this hunt for descriptors, but *not* for ordinary attribute
> lookups.

I'll describe the usecase that led to my proposal. I'm amongst other the primary
author (and sole maintainer) of PyObjC, which is a bridge between the Python
and Objective-C class/object models.  PyObjC defines a proxy class for every
(Objective-C) class in the Objective-C runtime and when an Objective-C object
is made available to Python code the PyObjC bridge creates a proxy object that 
is an instance of this proxy object.  This is simular what wxWidgets or PyQt do, 
but everything is done at runtime by introspecting the Objective-C runtime.

The first time a method is called the bridge looks for an Objective-C selector 
with the same name and adds that to the class dictionary. This works fine for normal
method lookups, by overriding __getattribute__, but causes problems with super:
super happily ignores __getattribute__ and peeks in the class __dict__ which may
not yet contain the name we're looking for and that can result in incorrect results
(both incorrect AttributeErrors and totally incorrect results when the name is
not yet present in the parent class' __dict__ but is in the grandparent's __dict__).

The current release of PyObjC "solves" this problem by providing a subclass of
super (objc.super) that should be used instead of the builtin one and that works,
although the implementation of this class is a gross hack.

Users's of PyObjC are currently oblivious of the problem because I sneak in objc.super
as a module's globals()['super'] when it imports PyObjC in the currently prefered 
way (which is using *-imports: "from Cocoa import *").  I'm currently migrating to
deprecating *-imports because those are bad for the usual reasons, but also because
framework binding modules are huge and using plain imports makes it possible to 
delay, and often even avoid, the cost of loading stuff from the framework binding
modules.  That switch will however make the problem of using __builtin__.super extremely
visible for PyObjC users.

That, and the implementation hack of objc.super, is why I started looking for a way
to cleanly provide a way to hook into the attribute resolution for super(), which ended
up as PEP 447.

Note that the description is slightly simplified from what PyObjC reall does, Objective-C
can (and does) have class and instance methods with the same name, because of that
all PyObjC classes have a meta class of the same name and that makes everything
even more complicated, but that should not be important for the previous description.

PyObjC also enables implementing Objective-C classes in Python, but that's also
not relevant for this discussion.


More information about the Python-Dev mailing list