[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