473,408 Members | 2,441 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,408 software developers and data experts.

Pythonic Abstract Base Class / Interface

My basic question:
If I have a specific interface which I know is going to be implemented
by a number of classes, but there is no implementation commonality
between them, what is the preferred form for this in Python?

In a staticly typed language like c++ or java, I'd describe the interface
first, then create the classes eithered derived from that ABC or
implementing that interface (same thing really). This was the first
thing I thought to do in python, but then rapidly realised I didn't
actually need to write anything in the base class - as long as code using
one of the implemented classes just tries to do things with it it
would just work. In fact, I didn't even need to make a base class at
all if the calling code never checks for type (as seems normal).

So, as I see it I could:
a) create a base class with stubs for all the interface and derive from that.
b) create an empty base class and derive from that.
c) just make the concrete classes directly with no inheritance commonality.

Is there a clear pythonic way, or does it depend a bit more on the
design of the specific program?

Tom
Jul 18 '05 #1
9 13255
Tom Evans <to*********@uk.co.yahoo.reverse> writes:
My basic question:
If I have a specific interface which I know is going to be implemented
by a number of classes, but there is no implementation commonality
between them, what is the preferred form for this in Python? [...] So, as I see it I could:
a) create a base class with stubs for all the interface and derive from that.
b) create an empty base class and derive from that.
c) just make the concrete classes directly with no inheritance commonality.

Is there a clear pythonic way, or does it depend a bit more on the
design of the specific program?


I'd say c) was probably the most pythonic, but it depends a bit. a)
might have some documentation value -- for instance, you could
document required relations between the methods in their docstrings.

Cheers,
mwh

--
In the 1950s and 60s there was a regular brain drain of young
Australians from the cities to London, but it was because of
money, culture and opportunity, not spiders.
-- Al Grant, ucam.chat, from Owen Dunn's review of the year
Jul 18 '05 #2
Michael Hudson wrote:
Tom Evans <to*********@uk.co.yahoo.reverse> writes:

My basic question:
If I have a specific interface which I know is going to be implemented
by a number of classes, but there is no implementation commonality
between them, what is the preferred form for this in Python?


[...]
So, as I see it I could:
a) create a base class with stubs for all the interface and derive from that.
b) create an empty base class and derive from that.
c) just make the concrete classes directly with no inheritance commonality.

Is there a clear pythonic way, or does it depend a bit more on the
design of the specific program?

I'd say c) was probably the most pythonic, but it depends a bit. a)
might have some documentation value -- for instance, you could
document required relations between the methods in their docstrings.


Another argument in favor of a) is that pychecker has an option to check if
methods only raising exceptions in a super-class are actually implemented in all
its sub-classes. So:

class MyInterface:
def spam(self):
raise NotImplementedError
class MyClass(MyInterface):
...

has actually more than a documentation value: pychecker should at least report a
warning if the method spam is not defined in MyClass.

HTH
--
- Eric Brunel <eric dot brunel at pragmadev dot com> -
PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com

Jul 18 '05 #3
>So, as I see it I could:
a) create a base class with stubs for all the interface and derive from that.
b) create an empty base class and derive from that.
c) just make the concrete classes directly with no inheritance commonality.


It's funny, I was actually thinking about the same thing not long before this
got posted.

Being a newcomer of sorts to Python, I can't really comment on what's
"Pythonic" or not as well as others can (and only Guido knows for sure), but I
can make some guesses. Pythonic in my mind is clear, concise, but flexible.
This is a case where you can't get all of them at the same time. The most
concise, of course, is answer C, at the possible expense of clarity and
flexibility. Clarity may be more important to you, and the winner for that is
A. (Somebody else suggested using docstrings in the stubs; I second that
opinion.) However, A is less concise.

A and B are both flexible, because you can implement more functions in the base
class, and poof! Derived classes gain the benefits right then and there. But of
course you have to make sure you don't break any of them (if you're careful and
you know what classes are derived from it, and I'm guessing you do, it
shouldn't be a problem). I'm inclined to say that B is more flexible than A,
because if you remove a stub function and some code somewhere relies on it
being called (whether or not it's a no-op), then a derived class that doesn't
define it will be broken. Of course, in practice, this isn't too likely...

To summarize:
C is concise and nothing else
B is concise (not quite as much as C), somewhat clear, flexible
A is clear, flexible (not quite as much as B), but not concise

I'm inclined to pick A, since I'm a bit of a clarity freak, but I don't really
feel that any one of these is more Pythonic than another on its own merits...it
kind of depends on the situation. If subclasses are likely to be small, I would
probably pick C or at most B and save some effort...if subclasses are likely to
be a significant size, I'd definitely pick A.

- Kef

Jul 18 '05 #4
Tom Evans wrote:
My basic question:
If I have a specific interface which I know is going to be implemented
by a number of classes, but there is no implementation commonality
between them, what is the preferred form for this in Python? ... Is there a clear pythonic way, or does it depend a bit more on the
design of the specific program?


The normal Python approach is currently to just rely on signature-based
polymorphism -- use inheritance to share implementation, but if you
have no implementation to share, there's no real reason to inherit.

Of course, people coming from languages where inheritance reigns will
not accept that easily and refer to such issues as:

-- in your 'interface class' you can implement the methods as raising
NotImplementedError, which will be clearer than the AttributeError
that happens upon trying to call the method on an instance of a
class that's meant to implement the interface but forgot the
method in question

-- inheritance is ALMOST always centered on sharing implementation --
in the case of exception handling, though, inheritance trees do matter

-- if you inherit you can typetest with isinstance rather than just
featuretest with hasattr (to me, that's a DEFECT of inheritance:-)

If you do have any useful features -- most often Template Method
design patterns -- to share among (some of) your concrete classes,
then by all means use inheritance for that. But, otherwise, I think
that keeping documentation in comments and docstring, and using
other language constructs (including inheritance0 for substantial
purposes and not "just to document things", is a preferable approach.
Alex

Jul 18 '05 #5
Tom Evans wrote:
My basic question:
If I have a specific interface which I know is going to be implemented
by a number of classes, but there is no implementation commonality
between them, what is the preferred form for this in Python?

In a staticly typed language like c++ or java, I'd describe the interface
first, then create the classes eithered derived from that ABC or
implementing that interface (same thing really). This was the first
thing I thought to do in python, but then rapidly realised I didn't
actually need to write anything in the base class - as long as code using
one of the implemented classes just tries to do things with it it
would just work. In fact, I didn't even need to make a base class at
all if the calling code never checks for type (as seems normal).

So, as I see it I could:
a) create a base class with stubs for all the interface and derive from that.
b) create an empty base class and derive from that.
c) just make the concrete classes directly with no inheritance commonality.

Is there a clear pythonic way, or does it depend a bit more on the
design of the specific program?


c), unless you have a compelling technical reason -> then a) with
NotImplementedErrors or like... I cannot see what's the b) option would
buy you anyway.

Work with the language, not against it.

Bruno

Jul 18 '05 #6
Bruno Desthuilliers wrote:
So, as I see it I could:
a) create a base class with stubs for all the interface and derive from that.
b) create an empty base class and derive from that.
c) just make the concrete classes directly with no inheritance commonality.

Is there a clear pythonic way, or does it depend a bit more on the
design of the specific program?


c), unless you have a compelling technical reason -> then a) with
NotImplementedErrors or like... I cannot see what's the b) option would
buy you anyway.


isinstance

</F>


Jul 18 '05 #7
Tom Evans wrote:
If I have a specific interface which I know is going to be implemented
by a number of classes, but there is no implementation commonality
between them, what is the preferred form for this in Python? ... Is there a clear pythonic way, or does it depend a bit more on the
design of the specific program?


I usually do something like

class AbstractBase:
def __init__(self):
if self.__class__ is AbstractBase:
raise NotImplementedError

def aMethod(self):
raise NotImplementedError

def anotherMethod(self):
raise NotImplementedError

--
Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/ \ We grow in time to trust the future for our answers.
\__/ Ruth Benedict
Jul 18 '05 #8
Erik Max Francis wrote:
Tom Evans wrote:
If I have a specific interface which I know is going to be
implemented by a number of classes, but there is no
implementation commonality between them, what is the preferred
form for this in Python?

...
Is there a clear pythonic way, or does it depend a bit more on
the design of the specific program?


I usually do something like

class AbstractBase:
def __init__(self):
if self.__class__ is AbstractBase:
raise NotImplementedError

[snip]

If you expect anyone else (or yourself when you've forgotten this
code) to implement another derived class (to implement the
interface), then you will also want to add doc strings to each of
the methods, so that an implementer of your interface knows what
the requirements are for each parameter, return values, etc.
Implementing the (empty) base class is a good way to provide
documentation on your interface.

Dave

--
Dave Kuhlman
http://www.rexx.com/~dkuhlman
dk******@rexx.com
Jul 18 '05 #9
Tom Evans wrote:
So, as I see it I could:
a) create a base class with stubs for all the interface and derive from that.
b) create an empty base class and derive from that.
c) just make the concrete classes directly with no inheritance commonality.


Thanks for all the responses. It would appear that there is no
One True Way. What I've learnt:

I was originally just whipping something up, not sure what the final
solution was going to look like. In that case, it would appear (c)
was the way to go.

If I wanted to document exactly what the interface should be once I'm sure
it's the right solution, (a) with document strings and raising
NotImplementedError might be a good place to put that documentation.
(btw, thanks -- I didn't know about NotImplementedError before)

On the face of it, (b) appears to be the loser. But it would give me
isinstance if I wanted it, and might allow me to convert more easily
from (a) to (c) in the future.

thanks to all,
Tom
Jul 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

15
by: Tee | last post by:
Hi, I have a base usercontrol with a method (blank method, no code), I have another few usercontrols that will inherit this base usercontrol, but I want to force all the usercontrol that...
12
by: phil hunt | last post by:
Suppose I'm writing an abstract superclass which will have some concrete subclasses. I want to signal in my code that the subclasses will implement certan methods. Is this a Pythonic way of doing...
18
by: Bradley | last post by:
I'm trying to determine if there's a general rule for when an Interface should used vs. an Abstract Class. Is there any design advantage to using one or the other? Brad
9
by: Sean Kirkpatrick | last post by:
To my eye, there doesn't seem to be a whole lot of difference between the two of them from a functional point of view. Can someone give me a good explanation of why one vs the other? Sean
7
by: jason | last post by:
In the microsoft starter kit Time Tracker application, the data access layer code consist of three cs files. DataAccessHelper.cs DataAcess.cs SQLDataAccessLayer.cs DataAcccessHelper appears...
0
by: mailforpr | last post by:
Hi. Let me introduce an iterator to you, the so-called "Abstract Iterator" I developed the other day. I actually have no idea if there's another "Abstract Iterator" out there, as I have never...
4
by: David Zha0 | last post by:
Hi, "when we call a virtual method, the runtime will check the instance who called the method and then choose the suitable override method, this may causes the performance drop down", is this...
6
by: Miguel Guedes | last post by:
Hello, I recently read an interview with Bjarne Stroustrup in which he says that pure abstract classes should *not* contain any data. However, I have found that at times situations are when it...
5
by: =?Utf-8?B?UmljaA==?= | last post by:
Greetings, I am actually a VB.Net guy, but I have worked somewhat with C++ and C#. I just want to ask about the relationship between Abstract Classes and Interfaces. My first question is if...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.