3

I'm trying to "monkey patch" an instance of list. Mind you, it isn't my list. I have no control over its creation. As far as I can see, this is not possible in 2.7. Am I right? Is it possible in 3.x?

2 Answers 2

6

No, you can't add or remove attributes on a list object, not in Python 2 and not in Python 3.

At best you can wrap such an object in another instance, one that implements the same attributes and methods as a list but passes on access to those to the wrapped listobject.

That wrapper could be implemented with the UserList.UserList() class:

try:
    # Python 2
    from UserList import UserList
except ImportError:
    # Python 3
    from collections import UserList

class ListWrapper(UserList):
    def extra_method(self):
        return """Hi! I'm an extra method on this "list" (wink, wink)"""

Demo:

>>> some_list = ['foo', 'bar', 'baz']
>>> wrapped_list = ListWrapper(some_list)
>>> len(wrapped_list)
3
>>> wrapped_list[1]
'bar'
>>> wrapped_list.extra_method()
'Hi! I\'m an extra method on this "list" (wink, wink)'
Sign up to request clarification or add additional context in comments.

9 Comments

Learn something new everyday :)
What's the advantage of using UserList over list in python 3?
@Dunes: If you subclass list, any method or operator that returns a new instance (such as concatenation) returns a regular list object again, while a UserList subclass will always return the wrapper class instead.
@Dunes: ah, yes, the __getitem__ method delegates straight to self.data.__getitem__. That's easily fixed, but still, that's unexpected given that __add__ and __mul__ return an instance of the class.
@Dunes: in Python 2, it works provided you don't use a stride (e.g. extended slice notation), because the __getslice__ method is used. But Python 3 removed that altogether (since __getitem__ was enough to handle all slicing with the slice() object). This is a bit of a bug, really.
|
2

Here is a lightweight way to add a single method to a single instance of a subclass of list

>>> import new
>>> L = ['f', 'o', 'o']
>>> M = type("list", (list, ), {})(L)
>>> M.bar = new.instancemethod(lambda self: self * 2, M)
>>> M.bar()
['f', 'o', 'o', 'f', 'o', 'o']

1 Comment

M + ['foo'] returns a regular list object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.