1
\$\begingroup\$

I need a class which behaves, and is in reality a list. However I need to ensure that the elements of this list are only of the list class itself.

In effect it is always a list of lists.

I wrote the following working code:

class MyListOfLists(list):

    def __init__(self, *args, **kwargs):
        super(MyListOfLists, self).__init__(self._my_args(args), **kwargs)

    def __setitem__(self, *args, **kwargs):
        super(MyListOfLists, self).__setitem__(self._my_args(args), **kwargs)

    def append(self, *args, **kwargs):
        super(MyListOfLists, self).append(self._my_args(args), **kwargs)

    def _my_args(self, args):
        return [e for e in args if isinstance(e,list)]

The following code to test:

my_list = MyListOfLists(['a','b'],['c','d'], 'a')
print(my_list)

which will gives the expected output:

[['a', 'b'], ['c', 'd']]

My question is: Apart from __init__, append() and __setitem__, which other functions/methods do I need to capture of the original list class in order to ensure that the elements are lists ?

Or to widen the question: would there be another way of doing this ?

[EDIT based on comments, 17-Nov-2017]

It is indeed bad design to drop non list types silently, hence the _my_args() function will look something like this:

def _my_args(self, args):
    if any(e for e in args if not isinstance(e,list)):
        raise TypeError
    return args

I would like to get back to the main question: what other methods of the list class do I really need to capture, do I really need to capture things like insert(), __add__, __iadd__ and possibly others ? or is there another way of doing this.

[EDIT based on self tinkering]

My code looks like this at the moment, questions remain the same:

class MyListOfLists(list):

    def __init__(self, *args, **kwargs):
        super(MyListOfLists, self).__init__(self._my_args(args), **kwargs)

    def __setitem__(self, i, *args, **kwargs):
        super(MyListOfLists, self).__setitem__(i, *self._my_args(args), **kwargs)

    def append(self, *args, **kwargs):
        super(MyListOfLists, self).append(*self._my_args(args), **kwargs)

    def insert(self, i, *args, **kwargs):
        super(MyListOfLists, self).insert(i, *self._my_args(args), **kwargs) 

    def extend(self, *args, **kwargs):
        super(MyListOfLists, self).extend(*self._my_args(args), **kwargs)

    def _my_args(self, args):
        if any(e for e in args if not isinstance(e,list)):
            raise TypeError
        return args
\$\endgroup\$
  • 4
    \$\begingroup\$ Why would you want it to silently drop non-list elements? Please provide more context, because at first glance this looks like a bad design. \$\endgroup\$ – 200_success Nov 16 '17 at 19:03
  • \$\begingroup\$ @200_success you are absolutely right, I should have done this before posting, so really raise TypeError when an element is not of the correct type. I have updated the post above. \$\endgroup\$ – Edwin van Mierlo Nov 17 '17 at 8:16
  • \$\begingroup\$ @200_success would you be so kind to give me a hint on why this is a bad design, so I can improve my design and code? -- appreciated ! \$\endgroup\$ – Edwin van Mierlo Nov 23 '17 at 9:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.