Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: How can I inherit from the built-in list type?

I want to add some attributes to the built-in list type, so I wrote this:

class MyList(list):
    def __new__(cls, *args, **kwargs):
        obj = super(MyList, cls).__new__(cls, *args, **kwargs)
        obj.append('FirstMen')
        return obj

    def __init__(self, *args, **kwargs):
        self.name = 'Westeros'

    def king(self):
        print 'IronThrone'

if __name__ == '__main__':
    my_list = MyList([1, 2, 3, 4])
    print my_list

but my_list contains only the element 'FirstMen'. Why my __new__ doesn't work here? And how should I inherit from a built-in type like list? Is it the same for the immutable types like str?

like image 985
pjhades Avatar asked Feb 24 '12 14:02

pjhades


People also ask

How do you inherit a list in Python?

To do this in Python, you can inherit from an abstract base class, subclass the built-in list class directly, or inherit from UserList , which lives in the collections module. In this tutorial, you'll learn how to: Create custom list-like classes by inheriting from the built-in list class.

What is a inbuilt Python function for inheritance?

The function isinstance() returns True if the object is an instance of the class or other classes derived from it. Each and every class in Python inherits from the base class object . >>> isinstance(t,Triangle) True >>> isinstance(t,Polygon) True >>> isinstance(t,int) False >>> isinstance(t,object) True.

How do you inherit in Object Oriented Programming in Python?

Use the super() Function By using the super() function, you do not have to use the name of the parent element, it will automatically inherit the methods and properties from its parent.

What is __ repr __?

Python __repr__() function returns the object representation in string format. This method is called when repr() function is invoked on the object. If possible, the string returned should be a valid Python expression that can be used to reconstruct the object again.


2 Answers

The list type usually does the actual initialisation of the list inside its __init__() method, as it is the convention for mutable types. You only need to overwrite __new__() when subtyping immutable types. While you can overwrite __new__() when subclassing list, there is not much point in doing so for your use case. It's easier to just overwrite __init__():

class MyList(list):
    def __init__(self, *args):
        list.__init__(self, *args)
        self.append('FirstMen')
        self.name = 'Westeros'

Also note that I recommend against using super() in this case. You want to call list.__init__() here, and not possibly anything else.

like image 133
Sven Marnach Avatar answered Oct 17 '22 21:10

Sven Marnach


First of all, are you doing this as an exercise to understand __new__? If not, there is almost certainly a better way to do what you're trying to do. Could you explain what you'd like to achieve here?

That said, here's what's happening in your example:

  1. You invoke MyList([1,2,3,4])
  2. This first invokes MyList.__new__(MyList,[1,2,3,4])
  3. Your implementation calls list.__new__(MyList,[1,2,3,4]) This returns a new instance of MyList, with no elements. list.__new__ does not populate the list. It leaves that to list.__init__, which is never called.
  4. Your __new__ method appends 'FirstMen' to the empty MyList instance.
  5. Your __new__ method returns the instance of MyList.
  6. MyList.__init__([1,2,3,4]) is invoked.
  7. It sets the name attribute to 'Westeros'.
  8. It returns.
  9. The instance is assigned to my_list and printed.

See here for an explanation of __new__: http://docs.python.org/reference/datamodel.html#basic-customization

like image 34
Weeble Avatar answered Oct 17 '22 21:10

Weeble