 |
 |
glyf | |
 |
 |
 |
 |
|
 |
 |
class A(object): def m(self, alpha): print 'A.m', alpha
class B(A): def m(self, alpha, beta): print 'B.m', alpha, beta super(B, self).m(alpha)
class C(B): def m(self, alpha, beta, gamma): print 'C.m', alpha, beta, gamma super(C, self).m(alpha, beta)
class D(B): def m(self, alpha, beta, gamma, delta): print 'D.m', alpha, beta, gamma, delta super(D, self).m(alpha, beta)
class E(C, D): def m(self, alpha, beta, gamma, delta, epsilon): print 'E.m', alpha, beta, gamma, delta, epsilon x = ??? super(E, self).m(alpha, *x)
E().m(1, 2, 3, 4, 5)
|
 |
 |
 |
 |
|
 |
 |



 |
 |
 |
 |
 |
From: terrycojones |
Date:
April 9th, 2007 08:30 pm (UTC)
|
| (Link) |
|
Re: One way to do it
|
Hi Glyph.
This sort of thing is better done with a whiteboard and code and maybe beer. There were lots of other things I could have said in my original post (some are mentioned in my python-dev posts) about why what I sent is pretty flexible.
First of all, if classes don't use this style then yes you can't do anything except try to pass them their arguments as they're wanted (positional, keyword) and as they're named. OTOH, if you're using my dictionary style you can still pass args _through_ an non-cooperating class if it's polite enough to pass on its **kwargs. Also, you've very unlikely to break a non-cooperating class if you put something obscure like __margs__ into the keywords. I guess all this is obvious, and your general point is taken.
I'm not sure why you say it's impossible to write (implying you write the whol hierarchy, all classes cooperate) mixins. Why not describe something that you think can't be done and I'll have a go? I certainly feel like I can re-define lower methods (re-define = change signature?) and have things continue to work, and even that I can do that in isolation without informing the authors of subclasses that I'm doing it, or even knowing if any subclasses do or will exist. That's part of the attraction of what I posted. Of course if you make an incompatible signature change (as opposed to a signature change that makes an arg optional or adds an optional keyword arg) then people calling your class are going to have to adjust - there's no way around that.
Why can mixins pretty much never define __init__? You don't inherit object's __init__ unless you call it. I don't understand your final comment either. Is this because object's __init__ does (or will soon) raise an exception if its argument list isn't empty?
If that's what you're meaning, you can have cooperating classes along the chain del their args out of the dictionary. It's perfectly safe and reasonable for them to do that - in fact to be most safe they should pull out their args, del from the dictionary, then call their superclasses, then use their own args. This makes sure that a super class can't mess with your args. Hopefully this makes sense - I can give an example if not. So if all classes cooperate and del their key from the dict, then when you hit object's __init__ the dict is (almost) empty. It actually contains the single key (like __margs__) which is an empty dict... Maybe that's what you meant?
Thinking about this sort of thing was what lead me to say in the python-dev mailing that if python were changed to allow None as a key in keyword args, then all classes could stash their args in there and object's __init__ could verify that it had no positional args and that its **kwargs contained (at most) None, and that that was an empty dict. That would work, it would be backward compatible (since Python currently does not allow None as a keyword arg), but of course it requires changing Python itself. I can give an example if that's not clear (in summary, use None instead of __margs__ in my example here).
All this was mentioned briefly in my original posting.
This morning I was thinking (again) about trying to write a decorator to hide some of the boilerplate code involved in doing this stuff. But I'm also trying to avoid thinking about this stuff in general :-)
Terry
|
 |
 |
 |
 |
|

|
 |
 |