[Please excuse poor email format... I've just been moved=20 to outlook and haven't yet figured out how to make it behave like a normal email program.] John, I really like your proposal!!! The main thing that I like about it is that, as you say: "It's also a lot easier to explain" That's usually a sign of a good design... when it all falls into place and becomes simple. I will admit, I've been trying to follow the various interface suggestions and have mostly been getting confused. This is simple and elegant, even if a few bits would improve with tweaking. Here is a running commentary on things I liked and disliked: 1. You create a new built-in type called "interface" with the special property that it does NOT appear in __bases__ even if declared to do so. I like this. Your syntax for the most common case of=20 supporting an interface looks like this: class C(object, I): <... code here ...> If we DIDN'T create a "special" type (special because Python has to omit pure interfaces in generating __bases__), then things could still work by some sort of declaration after C is created: class C(object): <... code here ...> declareItImplements(C,I) But that's putting it in the wrong place. The declaration to support an interface should be easy to type and to read (in the=20 common case), and should come at the TOP of the declaration of the class, not the end. So I like this. 2. You have a "magic class" __binding__. This sounds odd. Python hasn't ever used a "magic class" before. But it certainly makes the syntax simple. After all, you need to define a bunch of methods (the methods needed to conform to the interface). Declaring a class is the handy way to define a bunch of methods. So I think this is a little weird, but I don't really object. If there's another solution, though, I'd like to hear it. 3. Where does the "binding" live? Creating some sort of "global binding registry" is really not a good idea. Global is just bad, it becomes hard to find where things were set, which causes mysterious code failures, and so forth. At first, that's what I thought you were doing, but a closer look changed my mind. It seems to me that when you create a magic "__binding__" class what you are ACTUALLY doing is adding to a list of "classes implementing it" which is maintained in and associated with I,=20 the interface object. That has ABSOLUTELY NO effect on anyone who is not using the interface, and it feels like the "right" place to store this information. So I if I understand this correctly, I like it. 4. You make use of the interface by invoking it on an object: i =3D I(d) This has been discussed before, and it's a good approach. It allows for interfaces to return the object (thus not creating extra objects unnecessarily) or a proxy (thus giving lots of extra flexibility). Solidly supported. 5. You do NOT provide a way to do type declarations along with the interface. Python isn't picky about types, it naturally supports a policy=20 of allowing you to use any object that will do the job. That's a good thing for the language (even if my own preferences tend=20 toward a stricter typing system) and interfaces aren't about undermining it... just strengthening it! So +1 here. 6. You do NOT provide a way to declare preconditions, postconditions, or anything like this for the methods. In fact, there's no specification other than a docstring. For this I'm not sure. I like the minimalistic, simple approach of just giving a docstring, but I might also like some of the power of extra features. If I have to give up extra power to get a simple, workable approach then I'll live with it. 7. There's no way to "extend" interfaces, since inheriting from an interface means something different. That's OK with me -- seems like something one would only do when in a severe meta-programming mood. So all in all, I'm liking what I'm seeing here. -- Michael Chermside =20
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4