Bugs item #1306777, was opened at 2005-09-28 12:59 Message generated for change (Comment added) made by birkenfeld You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1306777&group_id=5470
Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: Python Interpreter Core Group: Python 2.4 Status: Open Resolution: None Priority: 5 Submitted By: Mattias EngdegÄrd (yorick) Assigned to: Nobody/Anonymous (nobody) Summary: Augmented assigment to mutable objects in tuples fail Initial Comment: >>> t=(set([2]),) >>> t[0] |= set([7]) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: object does not support item assignment but the contained set is mutable, and in fact: >>> t[0].__ior__(set([7])) set([2, 7]) >>> t (set([2, 7]),) If I use a mutable container (a list) in the first case, it works: >>> u=[set([2])] >>> u[0] |= set([7]) >>> u [set([2, 7])] But note that the list has not been mutated - only the set, so there would be no need for a mutable container. This is highly counter-intuitive - augmented assigment should do in-place operations on mutable types (which it does) and should therefore pose no restriction on the mutability of the container (which fails). ---------------------------------------------------------------------- >Comment By: Reinhold Birkenfeld (birkenfeld) Date: 2005-09-28 14:41 Message: Logged In: YES user_id=1188172 The bytecode generation happens before any code is executed, so the generated bytecode for x |= y is always the same (except, perhaps, when constants are involved). ---------------------------------------------------------------------- Comment By: Mattias EngdegÄrd (yorick) Date: 2005-09-28 14:24 Message: Logged In: YES user_id=432579 Thank you for your analysis. I'm not intimitely familiar with the bytecodes, but one way would be to omit the writeback (STORE_SUBSCR) if the result of INPLACE_OR is identical to its input. This could probably be done without changing the bytecodes but might profit from some changes for speed and compactness. That is (pseudocode): _t1 = t[i] _t2 = inplace_or(_t1, a) if _t2 is not _t1: t[i] = _t2 Another variant would be to add indexed variants of the augmented assigment methods; that is, augmented variants of __setitem__, but that has other drawbacks. However, it might be useful in its own regard in some cases. ---------------------------------------------------------------------- Comment By: Reinhold Birkenfeld (birkenfeld) Date: 2005-09-28 14:17 Message: Logged In: YES user_id=1188172 Generally there are two possibilites for the __ixxx__ methods: 1) Modify self and return self 2) Create a new instance with desired attributes and return it (necessary for e.g. integers) The second case cannot be handled by immutable containers. Hmm, maybe PySequence_SetItem should check whether the assigned item is already there and then succeed. Attaching a minimal patch for PySequence_SetItem (not sure about PyObject_SetItem). ---------------------------------------------------------------------- Comment By: Michael Hudson (mwh) Date: 2005-09-28 13:50 Message: Logged In: YES user_id=6656 Yuck, I agree that that's pretty icky. But the disassembly makes things clear: >>> dis.dis(compile('t[0] |= a', '', 'single')) 1 0 LOAD_NAME 0 (t) 3 LOAD_CONST 0 (0) 6 DUP_TOPX 2 9 BINARY_SUBSCR 10 LOAD_NAME 1 (a) 13 INPLACE_OR 14 ROT_THREE 15 STORE_SUBSCR 16 LOAD_CONST 1 (None) 19 RETURN_VALUE In fact... >>> s = set([1]) >>> t = (s,) >>> t[0] |= set([2]) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: object does not support item assignment >>> s set([1, 2]) >>> Oof. Not sure what to do about this. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1306777&group_id=5470 _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com