1

I've got a class which contains a number of lists where whenever something is added to one of the lists, I need to trigger a change to the instance's state. I've created a simple demonstration class below to try to demonstrate what I'm trying to do.

Suppose I have a class like this:

 class MyClass:
     added = False

     def _decorator(self, f):
         def func(item):
             added = true
             return f(item)
         return func

     def __init__(self):
         self.list = [1, 2, 3]
         self.list.append = self._decorator(self.list.append)

Since a list is built in, I cannot change it's .append method

cls = MyClass() #gives me an AttributeError since '.append' is readonly

Ideally, I could do the following:

cls = MyClass()
cls.list.append(4)
cls.added #would be true

How should I go about this? Would subclassing list allow me to change it's behavior in this way? If so, how would I pass in the class's state without changing the methods signature?

Thanks!

Josh Hanna
  • 55
  • 5

2 Answers2

2

You cannot monkey-patch builtins, so subclassing is the only way (and actually better and cleaner IMHO). I'd go for something like this:

class CustomList(list):

  def __init__(self, parent_instance, *args, **kwargs):
    super(CustomList, self).__init__(*args, **kwargs)
    self.parent_instance = parent_instance

  def append(self, item):
      self.parent_instance.added = True
      super(CustomList, self).append(item)


class MyClass(object):
    added = False

    def __init__(self):
        self.list = CustomList(self, [1,2,3])


c = MyClass()
print c.added  # False
c.list.append(4)
print c.added  # True
Community
  • 1
  • 1
Seb D.
  • 5,046
  • 1
  • 28
  • 36
  • Thanks, this should work for me! The main thing I didn't see was how to pass in the `parent_instance`, but your solution obviously covers that. – Josh Hanna Jun 25 '14 at 20:19
0

Would this suit your needs?

class MyClass(object):
    added = False

    def __init__(self):
        self.list = [1,2,3]

    def append(self, obj):
        self.added = True
        self.list.append(obj)



cls = MyClass()
cls.append(4)
cls.added #true

It might be helpful to know what exactly you're trying to achieve.

ToonAlfrink
  • 2,501
  • 2
  • 19
  • 19
  • I oversimplified a bit. The reason your solution wouldn't work is because the parent class (`MyClass`) contains more than one child list. I could, of course, implement a 'append' for each one, like `append_list1`, `append_list2`, etc, but that doesn't feel particularly elegant. – Josh Hanna Jun 25 '14 at 20:17