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


_______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to