Yo you donβt need to redefine all list methods - __setitem__, __init__ and \ append should be enough - you can have an insert and some others. You can write __setitem__ and __getitem__ to call the __set__ and __get__ methods in the special "Thing" class, just like the descriptors do.
Here is a quick example - maybe something like what you want:
class Thing(object): def __init__(self, thing): self.value = thing self.name = str(thing) id = property(lambda s: id(s))
Example:
>>> a = ThingList(range(3)) >>> a.append("three") >>> a [I am a 0, I am a 1, I am a 2, I am a three] >>> a[0].id 35242896 >>>
- change -
The OP commented: "I really hoped that there would be an opportunity to get all the functionality from the list - adding, expanding, fragments, etc., and just need to redefine the behavior of get / set item."
So, the way it is - you really need to redefine all the relevant methods in this way. But if we want to avoid just a large number of code plates with many functions that perform almost the same thing, new, overridden methods can be generated dynamically - all we need is a decorator to change ordinary objects to Things for all operations that set values:
class Thing(object): # Prevents duplicating the wrapping of objects: def __new__(cls, thing): if isinstance(thing, cls): return thing return object.__new__(cls, thing) def __init__(self, thing): self.value = thing self.name = str(thing) id = property(lambda s: id(s)) #... def __repr__(self): return "I am a %s" %self.name def converter(func, cardinality=1): def new_func(*args): # Pick the last item in the argument list, which # for all item setter methods on a list is the one # which actually contains the values if cardinality == 1: args = args[:-1] + (Thing(args[-1] ),) else: args = args[:-1] + ([Thing(item) for item in args[-1]],) return func(*args) new_func.func_name = func.__name__ return new_func my_list_dict = {} for single_setter in ("__setitem__", "append", "insert"): my_list_dict[single_setter] = converter(getattr(list, single_setter), cardinality=1) for many_setter in ("__setslice__", "__add__", "__iadd__", "__init__", "extend"): my_list_dict[many_setter] = converter(getattr(list, many_setter), cardinality="many") MyList = type("MyList", (list,), my_list_dict)
And it works like this:
>>> a = MyList() >>> a [] >>> a.append(5) >>> a [I am a 5] >>> a + [2,3,4] [I am a 5, I am a 2, I am a 3, I am a 4] >>> a.extend(range(4)) >>> a [I am a 5, I am a 0, I am a 1, I am a 2, I am a 3] >>> a[1:2] = range(10,12) >>> a [I am a 5, I am a 10, I am a 11, I am a 1, I am a 2, I am a 3] >>>