[Python-Dev] copy confusion

Phillip J. Eby pje at telecommunity.com
Wed Jan 12 00:40:18 CET 2005


At 02:58 PM 1/11/05 -0800, Guido van Rossum wrote:
>[Phillip]
> > Looks like a bug to me; it breaks the behavior of classic classes, since
> > type(classicInstance) returns InstanceType.
>
>I'm not so sure. I can't seem to break this for classic classes.

Sorry; I was extrapolating from what I thought was Fredrik's description of 
this behavior as a bug, and examining of the history of the code that he 
referenced.  I saw that the current version of that code had evolved 
directly from a version that was retrieving instance.__copy__; I therefore 
assumed that the loss-of-feature Fredrik was reporting was that.

That is, I thought that the problem he was experiencing was that classic 
classes no longer supported __copy__ because this code had changed.  I 
guess I should have looked at other lines of code besides the ones he 
pointed out; sorry about that.  :(


>The only thing this intends to break, and then only for new-style
>classes, is the ability to have __copy__ be an instance variable
>(whose value should be a callable without arguments) -- it must be a
>method on the class. This is the same thing that I've done for all
>built-in operations (__add__, __getitem__ etc.).

Presumably, this is the actual feature loss that Fredrik's describing; i.e. 
lack of per-instance __copy__ on new-style classes.  That would make more 
sense.



> > However, it also looks like it might have been introduced to fix the
> > possibility that calling '__copy__' on a new-style class with a custom
> > metaclass would result in ending up with an unbound method.  (Similar to
> > the "metaconfusion" issue being recently discussed for PEP 246.)
>
>Sorry, my head just exploded. :-(

The issue is that for special attributes (like __copy__, __conform__, etc.) 
that do not have a corresponding type slot, using getattr() is not 
sufficient to obtain slot-like behavior.  This is because 
'aType.__special__' may refer to a __special__ intended for *instances* of 
'aType', instead of the __special__ for aType.

As Armin points out, the only way to fully emulate type slot behavior for 
unslotted special attributes is to perform a search of the __dict__ of each 
type in the MRO of the type of the object for which you wish to obtain the 
special attribute.

So, in this specific case, __copy__ does not have a type slot, so it is 
impossible using getattr (or simple attribute access) to guarantee that you 
are retrieving the correct version of __copy__ in the presence of metaclasses.

This is what Alex and I dubbed "metaconfusion" in discussion of the same 
issue for PEP 246's __adapt__ and __conform__ methods; until they have 
tp_adapt and tp_conform slots, they can have this same problem.

Alex and I also just speculated that perhaps the stdlib should include a 
function that can do this, so that stdlib modules that define unslotted 
special attributes (such as __copy__) can ensure they work correctly in the 
presence of metaclasses.



More information about the Python-Dev mailing list