PEP 245

Michel Pelletier michel at digicool.com
Tue Apr 3 13:49:58 EDT 2001


On Sun, 1 Apr 2001, Alex Shindich wrote:

> I know I am going to get hate mail for this, but I have to get it off my
> chest!
>
> I would like to get a few questions answered:

Sure.

> 1. What is the point of interfaces without static typing?

To assert a contract is one.  To separate various implementations of the
same interface without them loosing a common usage is another.

> All that a proposed definition of an interface guarantees, is that the
> concrete classes will implement methods with certain names; no more and no
> less.
>
> There is no guarantee that method doSomething declared in the
> interface has anything in common with the method doSomething declared in the
> concrete implementation class. Indeed, there is no requirement that
> methods take the same parameters, not to mention that type checking is
> impossible? What kind of contract is that? BTW, the return values are not
> being checked either.

No mandatory enforcement is being proposed.

> 2. At what point will the compliance with the interface definition be
> done, at compile time, or at run time?

There is no madatory compliance or interface enforcement proposed in 245.
These things are optional, and they should be optional.  Turn on for
unit-testing, debugging, etc, turn off for production and speed.

> If the definition compliance is checked at compile time, then it will
> be impossible to add implementation dynamically.

That's right, which is why the proposal doesn't work that way.

> Python has always
> allowed modifications to the instances at run time. Not that it is always
> pretty, but it is possible. Compile time checking would disallow this
> technique.
>
> If the compliance is checked at run time, then interface checking is as
> good as as simply assuming that the method is implemented. Today, I can
> compile code like "f.doSomething ()" without f actually implementing
> doSomething. At run time I would get an AttributeError thrown into my
> face. In fact, the run time compliance is available already.

Interfaces, strong or weak, are not going to solve any of these problems
in a magic bullet fasion. There's a million ways around even strong
interfaced languaged, even ones that go so far as to check pre and
post-condition contract boundaries.

As Bruce Eckell said at IPC9, Python doesn't assume your dumb.  We don't
want interfaces to assume that either.  No madatory checking, no compile
time enfocement, etc.

One of the major reasons for the PEP is to assert that an object can be
used in a certain way, without caring about how it is implemented.  It's
telling you something about what it can do, without you having to know the
difference between the flat-file implementation and the one that uses a
relational database.

Currently this ability in Python is weak, and is based on looking at
classes.  But classes are not meant to be explicit interfaces, they are
ways of sharing implementaiton.

> Also, will it be possible to instantiate classes that do not implement all
> the interface methods?

Of course, although you would be breaking the contract and be a bad, bad
little object.  Then again, the user could always run the object through a
verification step, our prototype implementation has a function that can do
that for you, but the verification is just method names and signatures.

> 3. I am just curious... Does any one smell Java here?

No, Java interfaces are just compile time enforcement.  The syntax is
vaguely similar.

> Not that I have
> anything against Java, but I just wonder why Python should turn into
> Java. Python is a wonderful, strong, and powerful OO language. It has a
> set of its own patterns. Why does it have to support every possible
> feature? If someone really misses strong typing and interfaces, maybe you
> are trying to use the wrong language for the task?

Perhaps, but again no strong typing system is proposed by PEP 245.

> May be, Java is a
> better language for this particular set of tasks? Or perhaps, you can
> implement the same set of features using Python's real power --
> introspection and run time binding.

Take me for example.  If I were a python object, I'd be an instance of a
class that is generalized by two other classes, my mom and dad.  That's my
type, my genetics.  Now, let's say you were a function that expected a
'Python programmer'.  You could wire that expectation to my implementation
(my class), but then, I'd be the only "kind" of python programmer you could
use.  You could wire it to my generalized classes, but then you could only
use me and my two sisters, and they're not python programmers.

What you want is anyone, anybody, regardless of their genetic
implementation, to work in your function because they assert "I am a python
programmer."  It's a contract, protocol, interface, call it what you will:

class Michel(Reg, Loretta) implements PythonProgrammer:
    pass

In terms of verification and enforcement, you can go through the expensive
task of verifying my previous employment, my academic history, my
contributions to python, etc, just once (verfication) or *every* time
you worked with me (enforcement) or you could use the much cheaper method
of trusting me when I say I am a Python programmer.  PEP 245 does not
specify the policy you can use, all are possible.

The idea of PEP 245 is to separate object introspection from
implementation.  For example, you can create an object that quacks and
swims like a dictionary, but will not work for you as the right hand
component of an "exec 'x=5' in dict" statment.  This is because the exec
code checks the object based on its type, on its genetic makeup, not on the
functionality it asserts itself to have.

Similar problems lead to a lot of "if hasattr(obj, __getitem__):" etc
code.  So it has a __getitem__, what is it? A dictionary? A list?  Both
objects have __getitem__.  What defines a "sequence" or a "mapping"?  How
do you know that this object that has a __getitem__ expects sequential
integer keys, or is mutable?  These things are currently just implied by
the implementation, and often wired to a specific type, and the source of
weird errors when you pass your code an object that has some method you're
trying to imply the object's "interface" with.

With interfaces, objects can assert they implement the SequenceInterface
or the MappingInterface, or the MutableMappingInterface etc., and you can
check for that without having to understand the type.

-Michel






More information about the Python-list mailing list