This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: irregular behavior within class using __setitem__
Type: Stage:
Components: Interpreter Core Versions: Python 2.3
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: capnstabn, ncoghlan
Priority: normal Keywords:

Created on 2005-10-08 07:27 by capnstabn, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (6)
msg26536 - (view) Author: capnSTABN (capnstabn) Date: 2005-10-08 07:27
i found two bugs vaguely similar to this posted but i 
think they were different bugs in theory, and both were 
deemed 'features' anyway so ... :p

basically the class is a modified list, being used as a 
queue

what happens is, when hotswapping the __setitem__ 
functionality, unless explicitly calling __setitem__, the 
old __setitem__ continues to be called

this is very odd and as far as i can tell the behavior is 
undocumented


class Queue(list):
def __setitem__(self, a, v):
print "old setitem"
def mysetitem(self, i, v):
print "new setitem"
def use_mysetitem(self):
self.__setitem__ = self.mysetitem

x = Queue()

x[1] = 2

x.__setitem__(2, 3)

x.use_mysetitem()
x[3] = 4

x.__setitem__(4, 5)
msg26537 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2005-10-08 08:09
Logged In: YES 
user_id=1038590

This problem doesn't exist in Python 2.4:

Py> class Queue(list):
...   def __setitem__(self, a, v):
...     print "old setitem"
...   def mysetitem(self, i, v):
...     print "new setitem"
...   def use_mysetitem(self):
...     self.__setitem__ = self.mysetitem
...
Py> x = Queue()
Py>
Py> x[1] = 2
old setitem
Py>
Py> x.__setitem__(2, 3)
old setitem
Py>
Py> x.use_mysetitem()
Py> x[3] = 4
old setitem
Py>
Py> x.__setitem__(4, 5)
new setitem
msg26538 - (view) Author: capnSTABN (capnstabn) Date: 2005-10-08 08:14
Logged In: YES 
user_id=1126596

err, yeh it does 8)
the last TWO prints should display new setitem
msg26539 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2005-10-08 08:22
Logged In: YES 
user_id=1038590

Ah, sorry. I was looking at the wrong part of the printout.
msg26540 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2005-10-08 08:34
Logged In: YES 
user_id=1038590

And now that I've read the bug report properly, I'm closing
it as "Not a bug" :)

To affect the operators you need to alter the slot on the
*class*, not on the instance, but your "use_mysetitem"
method only affects the current instance - it shadows the
slot in the instance dictionary, but the interpreter is only
interested in the slots in the class itself.

To make the method work, it needs to be a class method:

  def use_mysetitem(cls):
    cls.__setitem__ = cls.mysetitem
  use_mysetitem = classmethod(use_mysetitem)

Of course, it will then affect *all* instances of the class
once the change is made.

You can get per-instance swapping by writing the slot method
in such a way that it delegates to a normal method, which
you can then alter on a per-instance basis. The wisdom of
actually *doing* that is debatable though ;)
msg26541 - (view) Author: capnSTABN (capnstabn) Date: 2005-10-08 09:44
Logged In: YES 
user_id=1126596

omg! you're lucky people on freenode spared you a half hour 
of explaining that lol!

and after almost 4 hours of completely going around the world 
just to take one step backwards...

[05:38] <squ1g3e> what if i want to change the class within 
an instance method
[05:38] <squ1g3e> coz the whole method isnt a class method
[05:38] <TFK> Then you can use self.__class__

haha thanks!
History
Date User Action Args
2022-04-11 14:56:13adminsetgithub: 42461
2005-10-08 07:27:33capnstabncreate