Issue 28442: tuple(a list subclass) does not iterate through the list (original) (raw)

if you subclass a list, and cast it to tuple, the casting does not iterate through the list. (casing to list does)

for example, i needed a WeakList where the list only internally contains WeakReferences that gets deleted as soon as the object ref count goes to zero.. so:

import weakref

class WeakList(list):

def __init__(self, items = ()):
    super(WeakList, self).__init__([weakref.ref(i, self.remove) for i in items])

def __contains__(self, item):
    return super(WeakList, self).__contains__(weakref.ref(item))

def __getitem__(self, index):
    if isinstance(index, slice):
        return [i() for i in super(WeakList, self).__getitem__(index)]
    else:
        return super(WeakList, self).__getitem__(index)()

def __setitem__(self, index, item):
    if isinstance(index, slice):
        item = [weakref.ref(i, self.remove) for i in item]
    else:
        item = weakref.ref(item, self.remove)

    return super(WeakList, self).__setitem__(index, item)

def __iter__(self):
    for i in list(super(WeakList, self).__iter__()):
        yield i()

def remove(self, item):
    if isinstance(item, weakref.ReferenceType):
        super(WeakList, self).remove(item)
    else:
        super(WeakList, self).remove(weakref.ref(item))

def append(self, item):
    return super(WeakList, self).append(weakref.ref(item, self.remove))

write some test code:

class Dummy(): pass

a = Dummy() b = Dummy()

l = WeakList() l.append(a) l.append(b)

print(a) <__main__.Dummy instance at 0x7f29993f4ab8>

print(b) <__main__.Dummy instance at 0x7f29993f4b00>

print(l) [<weakref at 0x7f2999433e68; to 'instance' at 0x7f29993f4ab8>, <weakref at 0x7f2999433ec0; to 'instance' at 0x7f29993f4b00>]

print([i for i in l]) [<__main__.Dummy instance at 0x7f29993f4ab8>, <__main__.Dummy instance at 0x7f29993f4b00>]

print(list(l)) [<__main__.Dummy instance at 0x7f29993f4ab8>, <__main__.Dummy instance at 0x7f29993f4b00>]

print(tuple(l)) (<weakref at 0x7f2999433e68; to 'instance' at 0x7f29993f4ab8>, <weakref at 0x7f2999433ec0; to 'instance' at 0x7f29993f4b00>)

^ notice how you are getting weak references back instead of tuples.

(Siming, when you post a mixture of code and output, please comment out output with # so the example can be run as is.)

I cannot reproduce the difference reported. I added #s and ran the cut and pasted code (uploaded) on 2.7, 3.5, and 3.6 installed on Win 10. For 3.6,

Python 3.6.0b2 (default, Oct 10 2016, 21:15:32) [MSC v.1900 64 bit (AMD64)] on win32

For me, the tuple output is exactly the same as the list output, except for '()' versus '[]'. In 3.5+, 'instance' is changed to 'object' for both list and tuple.

(<__main__.Dummy object at 0x000001839C1F32E8>, <__main__.Dummy object at 0x000001839C384DA0>)

Siming, please cut and paste the interactive splash line, like the above, that tells us the binary and OS you used.