1

I'm trying to inherit from collections.MutableSequence:

class myList(MutableSequence):
   def __new__(cls,*kwargs):
      obj=MutableSequence.__new__(cls,*kwargs)
      return obj

I get the error:

>>>a=myList()
>>>TypeError: Can't instantiate abstract class ContactMapList with abstract methods __delitem__, __getitem__, __len__, __setitem__, insert

I did not get any errors when I was deriving my class directly from the built-in list class in the same fashion:

class myList(list):
   def __new__(cls,*kwargs):
      obj=list.__new__(cls,*kwargs)
      return obj

I've tried to search for ways to define a constructor for myList(MutableSequence) but with not luck :(

Marcin
  • 48,559
  • 18
  • 128
  • 201
jmborr
  • 1,215
  • 2
  • 13
  • 23

2 Answers2

2

An abstract base class is a contract. It's a list of promises that any class deriving from it must keep.

The promises each of the collections classes make are listed in the docs. For example, anything inheriting from MutableSequence will have __getitem__, __setitem__, __delitem__ and some more.

You can't instantiate a contract!


When you make a class that inherits from an abstract base class, you don't inherit the methods. (Well... see note below.) You inherit a bunch of "abstract methods" which are just placeholders. To fulfill the promise you made by inheriting from the ABC, you have to give definitions for these methods. They can do whatever you like, but they must be there.

Actually, the methods you inherit can be real methods and you can delegate to them with super(). This lets you specify default behaviours. But that's not often used.

Katriel
  • 120,462
  • 19
  • 136
  • 170
  • You can, in fact, instantiate a contract. This answer probably means nothing to anyone who doesn't already know what you are trying to convey. – Marcin Mar 23 '12 at 14:44
  • @Marcin `You can, in fact, instantiate a contract.` In what sense? How can you instantiate an abstract base class? – Katriel Mar 23 '12 at 14:59
  • Take a standard form of contract; fill it in. You have instantiated a contract. – Marcin Mar 23 '12 at 15:00
  • I think there's a misunderstanding over the word "contract". I said "a contract [is] a list of promises that any class deriving from it must keep". You can't make an instance of a list of promises! You have to -- as you said -- __fill it in__. That's the crucial step. – Katriel Mar 23 '12 at 15:06
  • A list of promises in the abstract is not a contract; it's a form of a contract. You're using a leaky metaphor that does little to illuminate. – Marcin Mar 23 '12 at 15:07
  • 2
    @Marcin The use of `contract` to describe interfaces is standard. See e.g. [the Java docs](http://docs.oracle.com/javase/tutorial/java/concepts/interface.html): `Interfaces form a contract between the class and the outside world.` It is _precisely_ a contract: it says "I will implement `thismethod` and `thatmethod` and `theothermethod`." – Katriel Mar 23 '12 at 15:15
  • No, it precisely isn't a contract. It promises that someone else will implement those methods. As to "standard", it is not that either - it just happens to be used elsewhere. If this amounts to a contract, then one can indeed instantiate a contract. If this were a tightly-drawn metaphor you wouldn't be having this trouble defending your use of it. – Marcin Mar 23 '12 at 15:21
1

You can't instantiate an abstract class; you can instantiate a non-abstract class. That answers your question.

The unanswered question is: why are you defining __new__ in the first place?

Marcin
  • 48,559
  • 18
  • 128
  • 201
  • Then what is the procedure to define a constructor for a derived class of this MutableSequence? Please bear with me because I'm quite __new__ to this :) – jmborr Mar 23 '12 at 14:40
  • 1
    @jmborr Why do you want to define a constructor? What's wrong with `__init__`? – Marcin Mar 23 '12 at 14:40
  • nothing, just my ignorance. I'm beginning to understand my error message, though. It means I have to override the mentioned abstract methods, right? – jmborr Mar 23 '12 at 14:56
  • @jmborr Yes, but also it suggests that you shouldn't implement `__new__` unless you have good reason. – Marcin Mar 23 '12 at 14:58
  • 1
    @jmborr Simple inheritance (plus a little bit) will do it. Implementing new is not simple inheritance, though - it's introductory-level magic. – Marcin Mar 23 '12 at 15:11
  • I just tried that now. I removed the __new__ constructor and derived class myList(MutableSequence). However, myList is still an abstract class! I get the "Can't instantiate abstract class myList" when I try myList(). How can I make myList a concrete class, then? – jmborr Mar 23 '12 at 15:17
  • @jmborr Did you minimally implement the required methods? You need to to do that. Pay attention to the docs to see which methods already have implementations you can just call with `super`, and which you really have to implement. – Marcin Mar 23 '12 at 15:23
  • 1
    I finally understood it! Yes, I will have to implement these 'virtual' methods or use 'super'. A million thanks for your patience and answers, Marcin. – jmborr Mar 23 '12 at 15:37
  • @jmborr No problem. It's always tough going from basic stuff to working outside of the usual examples. An acceptance is worth 15 thanks, btw ;) – Marcin Mar 23 '12 at 15:41