weakref.proxy behaviour in python 3.0

N

Nicholas Cole

Dear List,

I've searched for information on this without success. Has
weakref.proxy changed in Python 3? I couldn't see any note in the
documentation, but the following code behaves differently on Python
2.6.1 and Python 3:

import weakref
class Test(object): pass

realobject = Test()
pobject = weakref.proxy(realobject)
l = [pobject,]

print(realobject in l) # On python 2.6 this prints False, on Python 3 True.

Is this an expected change?

Best wishes,

Nicholas
 
M

Mark Dickinson

I've searched for information on this without success.  Has
weakref.proxy changed in Python 3?  I couldn't see any note in the
documentation, but the following code behaves differently on Python
2.6.1 and Python 3:

import weakref
class Test(object): pass

realobject = Test()
pobject = weakref.proxy(realobject)
l = [pobject,]

print(realobject in l)   # On python 2.6 this prints False, on Python 3 True.

So the change underlying what you're seeing is that comparisons in 3.x
'unwrap' the proxy, while in 2.x they don't:

Python 2.7 (r27:82500, Aug 15 2010, 14:21:15)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.False

Python 3.1.2 (r312:79147, Aug 20 2010, 20:06:00)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.True

It looks to me as though this could be a long-standing defect in
Python 2.x, unwittingly(?) corrected in Python 3.x when 3-way
comparisons were removed in favour of rich comparisons. See

http://svn.python.org/view?view=rev&revision=51533

For 2.7, the proxy source (in Objects/weakrefobject.c) defines a
'proxy_compare' function that's used in the 'tp_compare' slot for
proxy objects, and that proxy_compare function has code to unwrap the
proxy objects when necessary so that comparisons are done on the real
underlying objects.

*But* C-level tp_compare slots only ever get called when both objects
have the same type, so when comparing a real object with the proxy for
that object, that's never.

In 3.x, that's replace with a proxy_richcompare function for the
tp_richcompare slot.

So my guess is that the change was unintentional.

It's probably worth a bug report. Even if the behaviour isn't going
to change in either 2.x or 3.x (and it probably isn't), it might be
possible to clarify the docs.
 
N

Nicholas Cole

[SNIP]
So my guess is that the change was unintentional.

It's probably worth a bug report.  Even if the behaviour isn't going
to change in either 2.x or 3.x (and it probably isn't), it might be
possible to clarify the docs.

Dear Mark,

I think the docs should be fixed: it would be good to have a list of
key examples where the behaviour is different. Although the new
behaviour is better, it certainly tripped me up badly.

I'm happy to fill a report out, but since you seem to know much more
about the internals, I wonder if a bug report written by you would be
more useful!

Just in case it helps, one thing that does seem to be the case is that
two different proxy objects to the same real object get compared in
the same way on both versions. So this code:

a = weakref.proxy(the_real_object)
b = weakref.proxy(the_real_object)

this_list = [ a, ]

l.remove(a) # Obviously works on both - just here for clarity.

l.remove(the_real_object) # Fails on python 2.6

l.remove(b) # gives an empty list on python 2.6 and python 3.


Very best wishes,

Nicholas
 
M

Mark Dickinson

[SNIP]
So my guess is that the change was unintentional.
It's probably worth a bug report.  Even if the behaviour isn't going
to change in either 2.x or 3.x (and it probably isn't), it might be
possible to clarify the docs.

I think the docs should be fixed: it would be good to have a list of
key examples where the behaviour is different.  Although the new
behaviour is better, it certainly tripped me up badly.

I'm happy to fill a report out, but since you seem to know much more
about the internals, I wonder if a bug report written by you would be
more useful!

http://bugs.python.org/issue9658

Please do log in and add any extra comments you feel appropriate.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top