Why PEP 245?? 
Author Message
 Why PEP 245??

All:

Could someone explain to me what in PEP 245 would be new to python in
terms of functionality? I did read it, but must not have understood
it! :)

According to the PEP:

    The purpose of an interface is to document how
    to work with an object, not how the object is
    implemented.

If this is all (or a large part), then why not just doc-strings? With
pydoc documentation is now nicely done.

Basically, without some sort of "compile-time" check that classes
that use interfaces use them correctly or classes that expect other
classes are using an interface are actually doing so, what is the
benefit:

    Interfaces try to solve these problems by
    providing a way for you to specify a
    contractual obligation for your object....

But what enforces the contract?

  Quentin Crain

PS: Where do mixin classes fit? Or have they gone out of style?



Sun, 16 Nov 2003 06:20:32 GMT  
 Why PEP 245??

Quote:

> But what enforces the contract?

From what I understood of the PEP you are correct, there is nothing in it
that specifies how the contract would be enforced.  You also mentioned
doc-strings, again you are correct, doc-strings can be used as a primitve
way to describe interfaces.  I believe that the folks at Digital Creations
currently use doc-strings for exactly that purpose.  I think though that
they have found this method wanting for several reasons (The author of the
PEP works at Digital Creations I believe).  Here are some that I can think
of:

    No standard way to disambiguate documentation of a class's interface
from documentation about how blue the sky is, or what year it is, etc...

    Normal end-user documentation now obfuscated by special tokens intended
to be read by other classes, not humans.

    People's desire to use inheritance (the mix-ins you mentioned) to
express interface.  In my mind there is nothing unfashionable about
inheritance, it's simply a different relationship than the one expressed by
two classes having a common interface.  My elephant class may derive from my
mammal class, but that has nothing to do with whether or not I have Elephant
implement the turbo-boostable interface.

    Sometimes I code in Java, I can definitely say that the use of
interfaces in Java has saved me time.  There have been several occasions
where I was able to see that a class implemented a well-understood interface
and then not had to refer to the documentation anymore... I knew how it
worked.

Butler



Sun, 16 Nov 2003 16:02:52 GMT  
 Why PEP 245??

    ...

Quote:
>     The purpose of an interface is to document how
>     to work with an object, not how the object is
>     implemented.

> If this is all (or a large part), then why not just doc-strings? With

docstrings are not executable and hence not rigorous.  Code is
preferable to comments (and docstrings) because it does not
"get out of sync", or if it does that shows at once.  (docstrings
can have executable _examples_ thanks to doctest of course,
but that's not an executable 'spec').

Quote:
> Basically, without some sort of "compile-time" check that classes
    ...
> But what enforces the contract?

If not compile-time, then run-time, of course.  What else?

Quote:
> PS: Where do mixin classes fit? Or have they gone out of style?

No, why?  An object can implement multiple interfaces, of course.

Alex



Sun, 16 Nov 2003 15:23:01 GMT  
 Why PEP 245??

    ...

Quote:
>     Sometimes I code in Java, I can definitely say that the use of
> interfaces in Java has saved me time.  There have been several occasions
> where I was able to see that a class implemented a well-understood
interface
> and then not had to refer to the documentation anymore... I knew how it

I use COM a lot, and I can vouch for a similar effect *when interface
design doesn't badly violate the ISP* (when it does, interfaces become
useless -- http://www.objectmentor.com/publications/isp.pdf explains
it pretty well, IMHO).

Otoh, reading in Python docs "a list", "a sequence", "a file-like object",
"a function", and the like, never works as solidly -- that's because docs
are docs, not executable, not rigorous, not enforced.  Most of the places
that claim they want a function argument will work with any callable,
but not all; most that claim they want a dictionary want a real dictionary,
but some will make do with a user-defined mapping; and "file-like" is
a mistery -- the interface of 'file-like objects' is wide enough to break
the ISP, so it takes investigation in each case to determine exactly what
methods et al the function claiming it wants a file-like object does in
fact use (is .read() without argument enough, does it want .read(N)
instead, or perhaps .readline(), or .readlines(), or .xreadlines(), or...
oh, and, what about letting softspace be set and cleared, and tell,
seek, close, isatty, fileno, closed ... and we haven't started exploring
the _write_ side of things either!-).

Such fluidity is sometimes useful, but it does require exploratory
programming to deal with -- pseudo 'file objects' that mostly
report on what methods are being called/attributes accessed/&c
while trying to behave harmlessly, for example.  And you never
know whether in a next release the function that used to work
fine with your 'file-like object' that supports .read() but not
.read(N) will break -- you only (at best) discover what the current
version of the implementation is actually calling on the "file
like object", not what the contract is between the function and
the object you pass to it.  A formal, language-specified and
'executable' notion of interface would help (as long as ISP is
somehow *enforced*, I guess -- raising NotImplementedError
[like, in COM, returning E_NOTIMPL] implies the interface is
not well-segregated... such "partial conformance" removes much
of the usefulness, IMHO).

Alex



Sun, 16 Nov 2003 18:57:21 GMT  
 Why PEP 245??

Quote:
> I use COM a lot, and I can vouch for a similar effect *when interface
> design doesn't badly violate the ISP* (when it does, interfaces become
> a mistery -- the interface of 'file-like objects' is wide enough to break
> the ISP, so it takes investigation in each case to determine exactly what

ISP??? In most contexts, Internet Service Provider, but here, interface S??
P??


Sun, 16 Nov 2003 22:55:03 GMT  
 Why PEP 245??

Quote:
> ISP??? In most contexts, Internet Service Provider, but here, interface
S??
> P??

I downloaded the paper out of curiosity; in this context, ISP stands for
"Interface Segregration Principle".


Mon, 17 Nov 2003 01:02:30 GMT  
 Why PEP 245??
All:

First, let me start by saying if you believe I am not understanding
interfaces in general, please provide links and I will gladly return
with questions after having read them!!

Onward!

Matt:

    No standard way to disambiguate documentation
    of a class's interface from documentation about
    how blue the sky is, or what year it is, etc...

    There have been several occasions where I was
    able to see that a class implemented a
    well-understood interface and then not had to
    refer to the documentation anymore... I knew
    how it worked.

Alex:

    Code is preferable to comments (and docstrings)
    because it does not "get out of sync", or if it
    does that shows at once.

As it seems to be now, an Interface is similar to a class which has no
implementation, but *requires* doc-strings. But what keeps the
doc-strings meaningful?

Let me go out on a limb and post code (untested because I do not have
access to a build with interface implemented):

class square:
    def __init__(self):
        pass
    def show(self):
        "Doc-string specific to square.show"
        print """
*****
*   *
*   *
*****
"""

class circle:
    def __init__(self):
        pass
    def show(self):
        "Doc-string specific to circle.show"
        print """
 ***
*   *
*   *
 ***
"""

class triangle:
    def __init__(self):
        pass

Now we could add an interface:

interface ShowInterface:
    "Classes can _show_ themselves"

    def show():
        "Display ASCII representation of the object"

and I modify my class definition:

class square implements ShowInterface:

 <nothing else changes>

class circle implements ShowInterface:

 <nothing else changes>

class triangle implements ShowInterface:

 <nothing else changes>

But now what? What makes sure the doc-strings stay current or make
sense? Does a "ContractUnfulfilledError" occur when I create an
instance of 'triangle' because 'show' was never defined/implemented?
In short, what can I do now that I could not?

Thanks!!

  Quentin Crain



Mon, 17 Nov 2003 00:26:34 GMT  
 Why PEP 245??

Quote:
> All:

> First, let me start by saying if you believe I am not understanding
> interfaces in general, please provide links and I will gladly return
> with questions after having read them!!

If you know enough C++ to get by, Martin's site at
www.objectmentor.com is a great place to start.  The
amount of C++ reading/understanding skill you need
IS reasonably minimal there.

Alex



Mon, 17 Nov 2003 05:09:25 GMT  
 Why PEP 245??

Quote:
> > I use COM a lot, and I can vouch for a similar effect *when interface
> > design doesn't badly violate the ISP* (when it does, interfaces become

> > a mistery -- the interface of 'file-like objects' is wide enough to
break
> > the ISP, so it takes investigation in each case to determine exactly
what

> ISP??? In most contexts, Internet Service Provider, but here, interface
S??
> P??

Interface Segregation Principle.  Sorry, it was silly of me to assume any
TLA (Three Letter Acronym) would be recognizable without explanation --
there's just far too much overloading of them!

Alex



Mon, 17 Nov 2003 05:16:54 GMT  
 Why PEP 245??

Quote:

> As it seems to be now, an Interface is similar to a class which has no
> implementation, but *requires* doc-strings. But what keeps the
> doc-strings meaningful?

Nothing, other than good coding practise.  But that's true of all
doc-strings.

Quote:
> Let me go out on a limb and post code (untested because I do not have
> access to a build with interface implemented):

> class square:
>     def __init__(self):
>         pass
>     def show(self):
>         "Doc-string specific to square.show"
>         print """
> *****
> *   *
> *   *
> *****
> """

> class circle:
>     def __init__(self):
>         pass
>     def show(self):
>         "Doc-string specific to circle.show"
>         print """
>  ***
> *   *
> *   *
>  ***
> """

> class triangle:
>     def __init__(self):
>         pass

> Now we could add an interface:

> interface ShowInterface:
>     "Classes can _show_ themselves"

>     def show():
>         "Display ASCII representation of the object"

> and I modify my class definition:

> class square implements ShowInterface:

>  <nothing else changes>

> class circle implements ShowInterface:

>  <nothing else changes>

> class triangle implements ShowInterface:

>  <nothing else changes>

> But now what? What makes sure the doc-strings stay current or make
> sense? Does a "ContractUnfulfilledError" occur when I create an
> instance of 'triangle' because 'show' was never defined/implemented?
> In short, what can I do now that I could not?

According to the proposal, these definitions would not generate any
sort of error - and that's reasonable because even though triangle
doesn't satisfy the interface on definition, Python is sufficiently
dynamic that it could be changed on-the-fly to satisfy it; or maybe
triangle class is meant to be an abstract class with subclasses like
IsocelesTriangle and EquliateralTriangle which always satisfy the
interface (which would probably be bad design, but shouldn't be
outlawed, I guess).

What the PEP allows is run-time testing for compliance to an interface.
For example:

def showlist(mylist):
    for object in mylist:
        if implements(object, ShowInterface):
            object.show()
        else:
            print str(object)

This would fail if you fed it a list containing a triangle instance,
but that's a fairly easy error to detect.

The PEP would also assist debugging through assertions.  For example:

def describe(object):
    assert implements(object, ShowInterface)
    print "The object you have selected looks like:"
    object.show()

You can do these sort of tests in Python already, for example:

def implementsShowInstance(object):
    return (hasattr(object, "show") and callable(object.show))

but this sort of thing is tedious at best if you have lots of complex
interfaces, and still doesn't full capture all the information that the
interface gives, such as the number of arguments to show and any
default arguments (it's possible to discover these, but it is a lot of
work).

The problem you describe with the triangle class can be ameliorated as
described in the PEP by using the deferred method of the interface:

Showable = ShowInterface.deferred()

...

class triangle(Showable):
    ... # as above, doesn't have a show method

triangle.show()   # gives an explicit error message

But perhaps the most important reason for having something like the
interface proposal is that Python already uses the concept of
interfaces, but without any formal mechanism for supporting them in the
language.  There is talk about "file-like" objects and "callable"
objects and "sequences" and "mappings" in the documentation, and there
is a rough consensus amongst developers about what these interfaces
are, but no explicit definitions of exactly what methods an object
needs to be considered to satisfy the interface.

Hope this helps,
Corran



Fri, 21 Nov 2003 02:58:50 GMT  
 
 [ 10 post ] 

 Relevant Pages 

1. Pep 245

2. PEP 245

3. PEP 245: Python interfaces

4. Interfaces (a la PEP 245 and Zope)

5. Help with ReplaceAll() and Chr(245)

6. Scheme Digest V6 #245

7. TIP #245: Discover User Inactivity Time

8. ALGORITHM DESIGN BIBLIOGRAPHY - RESULTS (245 lines)

9. ALGORITHM DESIGN BIBLIOGRAPHY - RESULTS (245 lines)

10. ALGORITHM DESIGN BIBLIOGRAPHY - RESULTS (245 lines)

11. Pep 238 Why new // operator (Non-integer Division)

12. pep 308: why doing (almost) nothing suffices

 

 
Powered by phpBB® Forum Software