[Python-Dev] copy confusion

Alex Martelli aleax at aleax.it
Wed Jan 12 00:09:17 CET 2005


On 2005 Jan 11, at 23:58, Guido van Rossum wrote:
 ...
>>> cls = type(x)
>>> copier = _copy_dispatch.get(cls)
>>> if copier:
>>> return copier(x)
 ...
>>> is this a bug, or a feature of the revised copy/pickle design?
>> [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.

You can't, _copy_dispatch deals with those.
> 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.).

And a wonderful idea it is.
>> 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. :-(
>> I think I did this change (for all slots) to make the operations more
> efficient by avoiding dict lookups. It does have the desirable
> property of not confusing a class's attributes with its metaclass's
> attributes, but only as long as you use the operation's native syntax
> (e.g. x[y]) rather than the nominally "equivalent" method call (e.g.
> x.__getitem__(y)).

Unfortunately, we do have a problem with the code in copy.py:
class MetaCopyableClass(type):
 def __copy__(cls):
 """ code to copy CLASSES of this metaclass """
 # etc, etc, snipped
class CopyableClass:
 __metaclass__ = MetaCopyableClass
 # rest of class snipped
x = CopyableClass()
import copy
y = copy.copy(x)
kallisti:/tmp alex$ python x.py
Traceback (most recent call last):
 File "x.py", line 14, in ?
 y = copy.copy(x)
 File "/usr/local/lib/python2.4/copy.py", line 79, in copy
 return copier(x)
TypeError: __copy__() takes exactly 1 argument (2 given)
kallisti:/tmp alex$
See? copy.copy(x) ends up using MetaCopyableClass.__copy__ -- because 
of a getattr on CopyableClass for '__copy__', which gets the 
BOUND-METHOD defined in the metaclass, with im_self being 
CopyableClass.
I had exactly the same metabug in the pep 246 reference implementation, 
Armin Rigo showed how to fix it in his only recent post.
Alex


More information about the Python-Dev mailing list

AltStyle によって変換されたページ (->オリジナル) /