Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #40337 > unrolled thread

Is it correct this way to inherit from a list?

Started bygialloporpora <gialloporpora@gmail.com>
First post2013-03-02 18:02 +0100
Last post2013-03-03 15:40 -0500
Articles 10 — 7 participants

Back to article view | Back to comp.lang.python


Contents

  Is it correct this way to inherit from a list? gialloporpora <gialloporpora@gmail.com> - 2013-03-02 18:02 +0100
    Re: Is it correct this way to inherit from a list? Peter Otten <__peter__@web.de> - 2013-03-02 18:19 +0100
    Re: Is it correct this way to inherit from a list? Ian Kelly <ian.g.kelly@gmail.com> - 2013-03-02 10:22 -0700
    Re: Is it correct this way to inherit from a list? Ian Kelly <ian.g.kelly@gmail.com> - 2013-03-02 10:26 -0700
      Re: Is it correct this way to inherit from a list? gialloporpora <gialloporpora@gmail.com> - 2013-03-03 03:33 +0100
    Re: Is it correct this way to inherit from a list? Rick Johnson <rantingrickjohnson@gmail.com> - 2013-03-02 09:46 -0800
      Re: Is it correct this way to inherit from a list? gialloporpora <gialloporpora@gmail.com> - 2013-03-03 03:30 +0100
        Re: Is it correct this way to inherit from a list? Chris Angelico <rosuav@gmail.com> - 2013-03-03 14:18 +1100
        Re: Is it correct this way to inherit from a list? "Colin J. Williams" <cjw@ncf.ca> - 2013-03-03 09:21 -0500
          Re: Is it correct this way to inherit from a list? Jason Swails <jason.swails@gmail.com> - 2013-03-03 15:40 -0500

#40337 — Is it correct this way to inherit from a list?

Fromgialloporpora <gialloporpora@gmail.com>
Date2013-03-02 18:02 +0100
SubjectIs it correct this way to inherit from a list?
Message-ID<kgtbb9$3ps$1@tdi.cu.mi.it>
Hi all,
I would like to inherit from the list native class.
really I expected that was possible to use native list method without 
redefining them, for example the __repr__ method.

I don't know if i have made something wrong, this is my code (I obmit 
customized methods that I have added):

from os.path import exists

class vector(list):
	def __init__(self, *args):
		self._list = list(args)
		self._index = 0
	def __getitem__(self, key):
		return self._list[key]
		
	def __setitem__(self, key, value):
		self._list[key] = value
	def __len__(self):
		return len(self._list)
	def __iter__(self):
		return self
	def next(self):
		if self._index == len(self):
			self._index = 0
			raise StopIteration
		next = self._index
		self._index += 1
		return self[next

Is it correct or it exists another way to inherit from list class?


Sandro



[toc] | [next] | [standalone]


#40339

FromPeter Otten <__peter__@web.de>
Date2013-03-02 18:19 +0100
Message-ID<mailman.2779.1362244783.2939.python-list@python.org>
In reply to#40337
gialloporpora wrote:

> I would like to inherit from the list native class.
> really I expected that was possible to use native list method without
> redefining them, for example the __repr__ method.
> 
> I don't know if i have made something wrong, this is my code (I obmit
> customized methods that I have added):
> 
> from os.path import exists
> 
> class vector(list):

> def __getitem__(self, key):
>     return self._list[key]

[and many more]

> Is it correct or it exists another way to inherit from list class?

Have you considered subclassing collections.MutableSequence instead?
You cannot instantiate that class until you have overridden all its abstract 
methods.

[toc] | [prev] | [next] | [standalone]


#40340

FromIan Kelly <ian.g.kelly@gmail.com>
Date2013-03-02 10:22 -0700
Message-ID<mailman.2780.1362244998.2939.python-list@python.org>
In reply to#40337
On Sat, Mar 2, 2013 at 10:02 AM, gialloporpora <gialloporpora@gmail.com> wrote:
> Hi all,
> I would like to inherit from the list native class.
> really I expected that was possible to use native list method without
> redefining them, for example the __repr__ method.
>
> I don't know if i have made something wrong, this is my code (I obmit
> customized methods that I have added):
>
> from os.path import exists
>
> class vector(list):
>         def __init__(self, *args):
>                 self._list = list(args)

So here you have a list subclass, but instead of taking advantage of
that is-a relationship, you're creating a secondary list from the
arguments and attaching it to self._list in a has-a relationship.  The
net effect is that you actually have two separate list objects here,
with some methods operating on the list itself and some operating on
the attached list.  Try this instead:

class Vector(list):
    def __new__(cls, *args):
        return super(Vector, cls).__new__(cls, args)
    def __init__(self, *args):
        super(Vector, self).__init__(args)

The __new__ method here will receive the args in the style that you
want, and then pass them up the inheritance chain to the superclass
constructor, which will then just do the right thing.  The __init__
method is also overridden to match the modified argspec.  The
super().__init__() call is included for completeness; AFAIK it doesn't
actually do anything.

[toc] | [prev] | [next] | [standalone]


#40341

FromIan Kelly <ian.g.kelly@gmail.com>
Date2013-03-02 10:26 -0700
Message-ID<mailman.2781.1362245252.2939.python-list@python.org>
In reply to#40337
On Sat, Mar 2, 2013 at 10:22 AM, Ian Kelly <ian.g.kelly@gmail.com> wrote:
> class Vector(list):
>     def __new__(cls, *args):
>         return super(Vector, cls).__new__(cls, args)
>     def __init__(self, *args):
>         super(Vector, self).__init__(args)
>
> The __new__ method here will receive the args in the style that you
> want, and then pass them up the inheritance chain to the superclass
> constructor, which will then just do the right thing.  The __init__
> method is also overridden to match the modified argspec.  The
> super().__init__() call is included for completeness; AFAIK it doesn't
> actually do anything.

I retract that.  On further testing, it is actually the __init__
method that initializes the list contents, not the __new__ method.  So
this is all you need:

class Vector(list):
    def __init__(self, *args):
        super(Vector, self).__init__(args)

[toc] | [prev] | [next] | [standalone]


#40386

Fromgialloporpora <gialloporpora@gmail.com>
Date2013-03-03 03:33 +0100
Message-ID<kgucpb$sf4$2@tdi.cu.mi.it>
In reply to#40341
Risposta al messaggio di Ian Kelly :

> I retract that.  On further testing, it is actually the __init__
> method that initializes the list contents, not the __new__ method.  So
> this is all you need:
>
> class Vector(list):
>      def __init__(self, *args):
>          super(Vector, self).__init__(args)

Thanks, it works :-), it is simpler of my implementation, thank again.
Sandro


-- 
*gialloporpora: Il nuovo album degli Atoms for Peace (con Thom Yorke dei 
radiohead) disponibile live: http://t.co/3VgxNFrZ Un po' troppo 
elettronico per me * - http://bit.ly/ZmDCze
Sto ascoltando: *Pink Floyd – Us and Them * - http://bit.ly/ZmDC2m

[toc] | [prev] | [next] | [standalone]


#40345

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-03-02 09:46 -0800
Message-ID<1409c13b-60a6-4e87-a58c-52d5740e74d5@googlegroups.com>
In reply to#40337
On Saturday, March 2, 2013 11:02:14 AM UTC-6, gialloporpora wrote:

> I would like to inherit from the list native class. really
> I expected that was possible to use native list method
> without redefining them, for example the __repr__ method.
> 
> [...]
>
> class vector(list):
> 	def __init__(self, *args):
> 		self._list = list(args)
> 		self._index = 0

Here is where you go wrong. 

First of all why would you inherit from "list" and then create a new list as attribute, that seems a bit silly huh? If you want your custom list to "inherit" all the pre-defined methods of the python list type, then do so.

>>> class MyList(list):
	pass

>>> ml = MyList()
>>> dir(ml)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> ml
[]
>>> ml.append('cat')
>>> ml
['cat']
>>> ml.extend(range(5))
>>> ml
['cat', 0, 1, 2, 3, 4]
>>> ml.sort()
>>> ml
[0, 1, 2, 3, 4, 'cat']
>>> isinstance(ml, list)
True

Quacks like a list to me. In this case you did not need to call the superclass constructor explicitly; for example.

class MyList(list):
    def __init__(self):
        list.__init__(self)
        
...is really a waste of time because you will not have any options to pass to the super. 
    
>>> ml2 = MyList2()
>>> dir(ml2)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> ml2+[10,20,30]
[10, 20, 30]
>>> ml2
[]
>>> ml2.append('salt')
>>> ml2
['salt']
>>> isinstance(ml2, list)
True
            
If however you wanted to create a custom Tkinter widget, you would then need to pass the options from the derived class __init__ method into the superclass __init__ method, like this:
    
class MyButton(tk.Button):
    def __init__(self, master, **kw):
        tk.Button.__init__(self, master, **kw)

mb = MyButton(rootWindow, text='PushMe', command=helloButton)

What are you trying to achieve exactly? 

[toc] | [prev] | [next] | [standalone]


#40385

Fromgialloporpora <gialloporpora@gmail.com>
Date2013-03-03 03:30 +0100
Message-ID<kguckk$sf4$1@tdi.cu.mi.it>
In reply to#40345
Risposta al messaggio di Rick Johnson :

> What are you trying to achieve exactly?


I would like to implement a class (vector) to works with vectors, for 
example using scalar multiplication:
a*v = [a*v1, a*vn]
and a dual class for dual vector (the only method that I'll change is 
the __str__ method to print it as colun.
Sandro



-- 
*gialloporpora: Il nuovo album degli Atoms for Peace (con Thom Yorke dei 
radiohead) disponibile live: http://t.co/3VgxNFrZ Un po' troppo 
elettronico per me * - http://bit.ly/ZmDCze
Sto ascoltando: *Pink Floyd – Us and Them * - http://bit.ly/ZmDC2m

[toc] | [prev] | [next] | [standalone]


#40391

FromChris Angelico <rosuav@gmail.com>
Date2013-03-03 14:18 +1100
Message-ID<mailman.2810.1362280748.2939.python-list@python.org>
In reply to#40385
On Sun, Mar 3, 2013 at 1:30 PM, gialloporpora <gialloporpora@gmail.com> wrote:
> Risposta al messaggio di Rick Johnson :
>
>
>> What are you trying to achieve exactly?
>
>
>
> I would like to implement a class (vector) to works with vectors, for
> example using scalar multiplication:
> a*v = [a*v1, a*vn]
> and a dual class for dual vector (the only method that I'll change is the
> __str__ method to print it as colun.

Have you looked at NumPy? I haven't used it myself, but I understand
it's good for this sort of thing.

ChrisA

[toc] | [prev] | [next] | [standalone]


#40411

From"Colin J. Williams" <cjw@ncf.ca>
Date2013-03-03 09:21 -0500
Message-ID<kgvm96$94n$1@theodyn.ncf.ca>
In reply to#40385
On 02/03/2013 9:30 PM, gialloporpora wrote:
> Risposta al messaggio di Rick Johnson :
>
>> What are you trying to achieve exactly?
>
>
> I would like to implement a class (vector) to works with vectors, for
> example using scalar multiplication:
> a*v = [a*v1, a*vn]
> and a dual class for dual vector (the only method that I'll change is
> the __str__ method to print it as colun.
> Sandro
Numpy facilitates this sort of thing more efficiently than using a List.

Colin W.

[toc] | [prev] | [next] | [standalone]


#40421

FromJason Swails <jason.swails@gmail.com>
Date2013-03-03 15:40 -0500
Message-ID<mailman.2826.1362343256.2939.python-list@python.org>
In reply to#40411

[Multipart message — attachments visible in raw view] — view raw

On Sun, Mar 3, 2013 at 9:21 AM, Colin J. Williams <cjw@ncf.ca> wrote:

> On 02/03/2013 9:30 PM, gialloporpora wrote:
>
>> Risposta al messaggio di Rick Johnson :
>>
>>  What are you trying to achieve exactly?
>>>
>>
>>
>> I would like to implement a class (vector) to works with vectors, for
>> example using scalar multiplication:
>> a*v = [a*v1, a*vn]
>> and a dual class for dual vector (the only method that I'll change is
>> the __str__ method to print it as colun.
>> Sandro
>>
> Numpy facilitates this sort of thing more efficiently than using a List.
>

As a couple people have already pointed out, numpy is the way to go for
most scientific applications.  You have also been given good advice
regarding 'properly' inheriting from 'list' by calling the list.__init__
function.

The only thing I'll add here is that you can inherit from array.array
instead of list if you want a 'truly' numeric-vector without introducing
numpy as a dependency.  The advantage array.array has over list in this
instance is that it is type-restrictive for member data (it has to be
pre-declared and throws TypeError if you try to pass it a bad variable
type).

You can then proceed to override the __add__, __sub__, __mul__, and __div__
methods (and the in-place versions of these operators) to mimic vector
operations.  (By default, __add__ appends the rhs to the lhs and returns a
copy of that for array.array and list).

You can avoid all this work, however, and just use numpy.ndarray instead ;).

Good luck,
Jason

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web