[Python-3000] Iterators for dict keys, values, and items == annoying :) (original) (raw)

Ian Bicking ianb at colorstudy.com
Sat Apr 1 00:36:44 CEST 2006


Benji York wrote:

Alex Martelli wrote:

If the framework consuming X requested adaptation-to-X on all objects it's passed, That's not generally the way Zope 3 does it (and doesn't sound like a good idea to me). There are three ways (as I see it) adaptation is used in Z3. First, the traditional idea of an "adapter", in which something has the right state, but the wrong interface. That form of adaptation is used when plugging different components together (whether they are Z3 or come from other projects). In that way of using adaptation a function/method/whatever wants things that act in a particular way (duck typing). If I, as the user of the interface, have something I want to pass in that doesn't match I it to the appropriate interface the burden is on me to create something that matches expectations. People do that all the time today without an interface/adaption framework, they just write code that takes one thing and builds another. Greg Ewing wrote: This is the part that bothers me, I think. It seems like all these adaptation requests would be a huge burden on the framework developer. Not in the above scenario, when using adapters like that the burden is on the user. That might sound like a bad thing, but if they're exclusively using your library, they already have objects of the necessary type, if not they have an adaptation framework to help them do something they'd have to do anyway. The second way adaptation is used is as a general lookup facility. Say that I have a user object and I want to know their security information. Instead of building an API for looking up security descriptions from a user name that I have to pull out of the user object, I could instead register and adapter from IUser to ISecurityInfo, now I don't need any new APIs, I just so secinfo = ISecurityInfo(theuser). This form of adaptation is good for the "I have something and want more information about it" use case. It also adds some flexibility, the workings of the adapter can change without having to change all the client code as you'd have to do if you changed (for example) the parameters an API expected. The third way it's used is to make systems pluggable. You mentioned PyGUI, so say you had a schema describing a data entry form. You could use adaptation to decide which GUI widget would be used for each field. Looping over the form fields and adapting each to IWidget and getting back a TextField for a string, CheckBox for a boolean, etc. Then if the user has a nice TextField object with spell checking, they could just plug in a different adapter and all their fields would get the new widget without PyGUI having to support a plug-in framework.

This is where I start getting nervous about adaptation, that it is used for a few too many things.

For instance, ISecurityInfo(the_user) is essentially providing magic-method-like introspection, except potentially you don't need the cooperation of the object, and the fetching has a namespace (a method has only a name, but ISecurityInfo actually lives someplace specific).

Those are useful features, but is it adaptation? If not adaptation, what do we call it? I suspect, given the right name, some aspects of the implementation can be streamlined and it will become a much more sensible operation to people. Magic methods are workable but hardly perfect, and the typical way they usually get used is that some function knows about all "normal" types (especially the fundamental types that can't have methods added to them) and falls back on a magic method. It's not pretty, though honestly I don't know of particularly pretty techniques that other languages use.

The last item feels much more comfortable to me as generic functions (like in PJE's RuleDispatch). It covers the use cases where multi-adaptation seems to pop up, and to me multi-adapatation just looks like the poor man's generic functions implemented in terms of adaptation, because adaptation systems (well, Zope interfaces) have a nice declarative system and pattern matching facilities. But leveraging that just to avoid real generic functions seems wrong to me.

Adaptation-that-is-actually-adaptation feels more like views to me. You need a specific interface, but you want to be able to accept objects that are isomorphic to that interface. Finding the right view (aka adapter) is something that calls for all the kinds of mechanisms Zope interfaces have -- interfaces and declarations of views/adapters. But the promises that a view makes are much stronger than what an adapter makes in current systems. A view can only be a subset of what the original object provides, but that doesn't seem to be the norm for Zope adapters.

That said... is ISecurityInfo(the_user) a view of the user? Possibly, depending on how it is implemented. If it is implemented as "return self.security_info" then no, unless the_user.security_info is read-only. If the adapter is a proxy object that forwards everything to "the_user.security_info", then yes. But something still feels weird to me about it. And I suppose ISomeInterface(obj1, obj2) could create something that is a subset of the two objects. Hrm... the whole thing makes me feel funny, though. Maybe it's that I want adaptation to be reversable.

-- Ian Bicking / ianb at colorstudy.com / http://blog.ianbicking.org



More information about the Python-3000 mailing list