5

I am currently learning Python (from Java) and have a question on contracts.

Example: an application defines an interface that all plugins must implement and then the main application can call it.

In Java:

public interface IPlugin { 
  public Image modify(Image img); 
} 

public class MainApp {
   public main_app_logic() { 
     String pluginName = "com.example.myplugin"; 
     IPlugin x = (IPlugin) Class.forName(pluginName);
     x.modify(someimg);  
   }
}

The plugin implements the interface and we use reflection in main app to call it. That way, there's a contract between the main app and the plugin that both can refer to.

How does one go about doing something similar in Python? And also, which approach is better?

P.S. I'm not posting this on SO because I'm much more concerned with the philosophy behind the two approaches.

2
  • 5
    Just a note: Python is (very much) not Java, you'll have to adjust to the dynamic nature where a lot of Java constructs are overkill and not needed. There are uses for contracts in Python though. Commented Dec 9, 2012 at 15:46
  • 1
    en.wikipedia.org/wiki/Duck_typing#In_Python pretty much answers the question
    – vartec
    Commented Dec 9, 2012 at 15:47

2 Answers 2

9

Python's approach to this problem is is about as opposite as you can get to Java's approach.

In Python there are no contracts, restrictions, agreements, or requirements with respect to objects and their capabilities. An object is assumed to have any given method or property until you actually try to use it. If it works then it works, but if the attribute doesn't exist, then it's a runtime error. You can either try to catch that AttributeError before it blows up your program, or you can debug from the resultant stack trace.

If the method exists but returns the wrong type of result, then hopefully either you'll get an exception somewhere down the road that you can catch, or perhaps you'll get some sort of output sometime later that you'll alert you to your mistake.

As mentioned, you can use the abc module to define an Abstract Base Class and register your class as an implementation. This will throw a TypeError when you instantiate your class if it doesn't implement all of the abstract methods described in your abstract base class. There's obviously no way to check return types, though, since Python doesn't really have a concept of return types.

This really underscores the need for 100% code coverage on your unit tests for Python code. These mistakes can lay quietly undetected unless you exercise every piece of code under every allowable set of circumstances.

1
  • Thanks for the detailed answer -- especially for describing the right way of doing it as well as alternatives.
    – recluze
    Commented Dec 15, 2012 at 6:57
5

Python, being a dynamic programming language, does not usually require the rigidity of Java contracts.

If you are looking for a plugin-style registry, the python distribution packaging library setuptools provides methods to register "entry points"; using the pkg_resources module (part of the setuptools project) you can then enumerate everything registered for a given entry point, and different packages can register their plugins that way. See Explain Python entry points.

Python does provide 'contracts' of a sort, called Abstract Base Classes. Their purpose is more to test if an object can satisfy the contract, and is not normally used for discovery.

Last but not least, the add-on packages zope.interface and zope.component (part of the Zope Component Architecture) provide both a method to specify contracts, and the means to look up components registered as implementing a given contract.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.