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
?
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.
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.
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.
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.
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.
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:
MyList([1,2,3,4])
MyList.__new__(MyList,[1,2,3,4])
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.__new__
method appends 'FirstMen'
to the empty MyList
instance.__new__
method returns the instance of MyList
.MyList.__init__([1,2,3,4])
is invoked.name
attribute to 'Westeros'
.my_list
and printed.See here for an explanation of __new__
: http://docs.python.org/reference/datamodel.html#basic-customization
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With