[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