Interfaces In Python

last modified: December 21, 2007

PythonLanguage doesn't have interfaces like JavaInterfaces. If it's for MultipleInheritance, Python already has it, but for "contract compliance" it hasn't.


Not built-in, but ZopeApplicationServer has an 'interfaces' module that does pretty much everything you could want. The Twisted framework for AsynchronousProgramming also has a usable implementation of interfaces as regards contract compliance. -- MoeAboulkheir


There is a PEP for implementing Interface Syntax in Python. It's PEP-245 at http://www.python.org/peps/pep-0245.html.

It would be very nice when it's implemented, but it still can't guarantee the semantics (pre/post-conditions, and invariants) even if it's implemented. Yes, you should follow the documentation very carefully. If you are a good programmer it won't be any problem but if you are a rogue or novice programmer, what happens? If you're a rogue programmer, your code is going to stink anyway. If you're a novice, what are you doing bungling around with interfaces?

I do use UnitTests extensively when programming and apply them to interfaces compliance checking as well.

You know interfaces sometimes can deceive you -- it could be fictitious without semantic guarantee. With UnitTests, however, the interfaces can guarantee semantics as well.

The following code will tell, (If the client implements StackInterface with ListStack, she'll make a unittest module for that and name it "test_StackList". In the test, she just imports all the tests from StackInterface so that interface compliances are guaranteed. She might add some ListStack-specific test cases in the same module test_StackList.)

#------------------------------------------------
#StackInterface.py
import unittest

class StackInterface:  #or put this whole class as a doc string
    '''Anything that implements this should pass the unittests in
       StackInterface with its own MyImpl
    '''
    def push(self, anObject):
        raise NotImplementedError
    def pop(self):
        raise NotImplementedError
    def isEmpty(self):
        raise NotImplementedError

class _Object: #helper object representing _anything_
    pass

class TestStackInterface(unittest.TestCase):
    def setUp(self):
        self.stack=MyImpl()
    def testPushAndPop(self):
        o=_Object()
        self.stack.push(o)
        self.assertEqual(o, self.stack.pop())
    def testPopOnEmpty(self):
        self.assert_(self.stack.isEmpty())
        self.assertRaises(IndexError,self.stack.pop)
    def testPushAllAndPopAll(self):
        oList=[_Object() for i in range(10)]
        for each in oList:
            self.stack.push(each)
        oList.reverse()
        for each in oList:
            self.assertEqual(each, self.stack.pop())

MyImpl=StackInterface #please override this with the real implementation

if __name__=='__main__':  # you won't run this module directly though
    unittest.main()

#------------------------------------------------
#ListStack.py
from StackInterface import StackInterface
class ListStack(StackInterface):
    def __init__(self):
        self._s=[]
    def push(self, anObject):
        self._s.append(anObject)
    def pop(self):
        return self._s.pop()
    def isEmpty(self):
        return len(self._s)==0

#------------------------------------------------
#test_ListStack.py
import unittest

import StackInterface
from ListStack import ListStack
StackInterface.MyImpl=ListStack

from StackInterface import *  #if you want to implement several
                              #interfaces just import all of them here
if __name__=='__main__':
    unittest.main()

-- JuneKim


CategoryInterface CategoryPython


Loading...