[Interface-dev] zope.interface calling an interface with no arguments

Jim Fulton jim at zope.com
Thu Sep 1 09:14:35 EDT 2005


Steve Alexander wrote:
>>g = Graph(Default) # currently
> 
> 
> As things stand now, when you call an interface, it uses the same
> signature as 'adapt()' from PEP-246.
> 
> That is, you can say ISomething(obj) or ISomething(obj, default_value).
> 
> In the first case, an error is raised if the object cannot be adapted.
> In the second case, the default value is returned if the object cannot
> be adapted.
> 
> This is a nice syntax, but breaks a usability rule in that the behaviour
> of an API should not change semantics when you add an optional argument.

Agreed. It was a concious tradeoff of this rule against the convenience
of using the call syntax in this case.

> The syntax is also limiting, because it does not allow you to express
> multi-adaptation.
> 
> If we changed interfaces to allow multi-adaptation by directly calling
> the interface, then many lookups in Zope 3 would read more simply:
> 
>   view = IBrowserView(context, request)
 >
 > This is an example of an adaptation of two objects at once.  The factory
 > for this adapter takes not one argument, but two.  For example:
 >
 >   class MyBrowserView:
 >
 >       implements(IBrowserView)
 >
 >       def __init__(self, context, request):
 >           ...
 >
 > (This isn't quite a real example, but it gives the idea.)
 >
 > What to do with default values?  This can become an argument that you
 > must supply using a keyword, for explicitness.  The explicitness can
 > sort of counteract the problem of the semantic change, although I'm
 > weasling around the issue.
 >

I would like to have this. There is a problem with it, as I think we've
discussed before.

As you point out, iface(obj) has PEP-246 semantics.  In particular:

- if obj has a conform method, then it will be called

- If obj already provides iface, then obj is returned.

These two behaviours can't apply when adapting no objects, or
when adapting multiple objects. (We treat adapting 0 objects as
a case of multiadaptation.)  The component architecture supports
explicit multi-adaptation, as in:

   zope.component.getMultiAdapter((), IFoo)
   zope.component.getMultiAdapter((x, y), IFoo)
   zope.component.getMultiAdapter((obj, ), IFoo)

Note that the last example is not equivalent to:

   IFoo(obj)

because, in the multi-adaptation case, we don't check for __conform__
and we don't check whether obj already adapts the interface.

Allowing interface call to support multi-adaptation introduces a
more troubling sematic inconsistencey and an, IMO, unacceptable
ambiguity in the single-argument case.

This is more troubling to me than the problem with default.

I'd be happy to move default to being a keyword argument if it
wasn't for this other problem.

...

> Cool.  Have you thought about following the Zope convention of tagging
> interface names with a capital "I" at the start?  It sounds a bit
> hungarian, but it does help a lot when reading code.

Yup.

Jim

-- 
Jim Fulton           mailto:jim at zope.com       Python Powered!
CTO                  (540) 361-1714            http://www.python.org
Zope Corporation     http://www.zope.com       http://www.zope.org


More information about the Interface-dev mailing list