<br><br><div><span class="gmail_quote">On 4/20/07, <b class="gmail_sendername">Guido van Rossum</b> &lt;<a href="mailto:guido@python.org">guido@python.org</a>&gt; wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
On 4/20/07, Thomas Wouters &lt;<a href="mailto:thomas@python.org">thomas@python.org</a>&gt; wrote:<br>&gt; I&#39;ve had this near the top of my (Python) TODO list for a while, but I<br>&gt; haven&#39;t been able to find the time. I&#39;ve considered it while doing the
<br>&gt; dishes and such, though.<br><br>(Not in the shower? :-)</blockquote><div><br>Yes, there too, when I shower alone; I was going to spare everyone the visual though :)<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
&gt; I can think of two ways of doing the underlying<br>&gt; magic &quot;properly&quot;, and one way that&#39;s too ugly to think about:<br>&gt;<br>&gt;&nbsp;&nbsp;1) Add a new type of descriptor-hook, for associating an object with the
<br>&gt; class it is an attribute of. After class creation (in the metaclass<br>&gt; __init__), any object with this __associate__ (or whatever) hook gets it<br>&gt; called. It&#39;s only called for objects that are attributes of *that* class,
<br>&gt; not of any superclasses (since they will already be associated with the<br>&gt; superclass.) I&#39;m sure there are other uses for this hook, just not methods<br>&gt; that want to use super() -- like zope interfaces ;)
<br><br>Nice and elegant. Though what would the hook *do*? I.e. where does it<br>store the class reference for super to find? Perhaps this is where my<br>idea of a designated cell comes in handy (although you&#39;d end up with a
<br>cell per method instead of all methods sharing one cell).<br><br>Also, what arguments are passed to the hook? For this purpose the<br>class object is the only thing needed -- but is that always<br>sufficient?</blockquote>
<div><br>The hook would &#39;bind&#39; the function to the class -- in some unspecified way. Unspecified because I haven&#39;t thought that far ahead yet, and I don&#39;t forsee any particular difficulties. Either the function gets wrapped in an &#39;associated function&#39; type that knows which class it was defined in (so somewhat different from the current &#39;unbound method&#39; type, but not much) or we just store the associated-class in the existing function object (probably the better option.). In either case we need some new magic to pass this class-object to the actual code object, or give the code object a way to refer to the function object (sometimes also useful for other reasons; it&#39;s not an uncommon request, in newbie areas.)
<br><br>As for the arguments to this hook -- I guess passing the attribute name as well as the class object makes sense. It&#39;s not much more overhead, and there isn&#39;t much more we could sensibly pass that isn&#39;t easily available given the class object and attribute name.
<br><br>Phillip mentioned class decorators -- I&#39;d forgotten about those. I don&#39;t see much use for them myself, as metaclasses make much more sense to me, in particular because they are naturally inherited, whereas class decorators are (I assume) not inherited. I&#39;m not sure how they should -- or could -- work together with super. It would only be a problem if the class decorator returns a wrapper class, rather than mutate the class. I guess we&#39;d need a way to tell associated-functions &quot;instead of ever visiting this class, visit this wrapper class instead. But don&#39;t mess with MRO&quot;... I think. I&#39;m not entirely sure how class decorators would affect MRO, really.
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">&gt;&nbsp;&nbsp;2) Add a new argument to __get__ (or a new method that acts like __get__
<br>&gt; but with the extra argument, and is called instead of __get__ if it is<br>&gt; defined) where the extra argument is the class that the retrieved descriptor<br>&gt; is actually an attribute of. It currently (correctly) gets the class the
<br>&gt; attribute was retrieved through, which could be a subclass.<br><br>I&#39;m not so keen on this; calling an existing API with an extra<br>argument is fraught with transitional problems (2to3 notwithstanding).<br>And checking for two different special methods slows things down. I&#39;d
<br>propose to pass the class where it&#39;s found as the 3rd arg always,<br>since (almost) nobody uses this argument, but I&#39;m not sure of the<br>consequences for class methods.</blockquote><div><br>The consequence for classmethods would be bad. They would always get the class they were defined on as first argument, making them completely pointless. So, let&#39;s not do that :) 
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">(Of course, there&#39;s the issue what to do if we dynamically define a<br>new function, and poke it into a class as a method, and that function
<br>needs to use super. IMO it&#39;s fine to require such a function to use<br>the underlying super() machinery -- this must be an exceedignly rare<br>case!)</blockquote><div><br>It&#39;s easy to handle such cases if we flag super-syntax-using-functions specially (which is also easy.) type&#39;s __setattr__ can complain if such a function gets assigned to an attribute, or it could do the binding magic right then. Functions that don&#39;t use the super syntax will continue to work like usual. And super-syntax-using-functions can scream and shout when they get &#39;associated&#39; with more than one class, of course.
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">&gt; In both these cases, the (un)bound method object would end up with knowledge
<br>&gt; of the class it is defined in, and create a local variable with a<br>&gt; super-object for the &#39;super&#39; keyword to use.<br><br>Ah, so you propose to store it in a local variable. But where is it<br>stored before the function is called? I guess on the &quot;bound method&quot;
<br>object. But how is the value passed on as part of the call? I like a<br>cell a lot better because we have an established way to pass cells<br>into calls.</blockquote><div><br>As I mentioned above, I didn&#39;t really think about this part. By &#39;local variable&#39; I just mean that we don&#39;t use a global registry or some such ugly hack -- it&#39;s a reference, stored wherever, specific to that call.
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">&gt; There still are some grey areas<br>&gt; to solve -- what if classes share functions, what if functions share
<br>&gt; code-objects, etc. #2 is probably a better way to go about it than #1, in<br>&gt; that regard.<br><br>Sharing functions is very rare and IMO it&#39;s okay if the mechanism<br>doesn&#39;t work in that case -- as long as it fails loudly. Sharing code
<br>objects shouldn&#39;t be a problem -- code objects are immutable anyway,<br>cells are associated with the function object, not with the code<br>object.</blockquote><div><br>Agreed. <br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
&gt; There&#39;s also the question of what the super keyword itself should look like,<br>&gt; e.g.<br>&gt;<br>&gt;&nbsp;&nbsp; # declaration-style, no dot<br>&gt;&nbsp;&nbsp; res = super currentmethod(arg, arg)<br>&gt;&nbsp;&nbsp; # treat super like self
<br>&gt;&nbsp;&nbsp; res = super.currentmethod (arg, arg)<br>&gt;&nbsp;&nbsp; # treat super like self.currentmethod<br>&gt;&nbsp;&nbsp; res = super(arg, arg)<br>&gt;<br>&gt; I think super.currentmethod(arg, arg) makes the most sense, but that may be<br>
&gt; because it most closely resembles the current practice. However, it may call<br>&gt; the &quot;wrong&quot; supermethod when the class does, for instance, &#39;__repr__ =<br>&gt; __str__&#39;.<br><br>Depends on how you define &quot;wrong&quot;. :-)
</blockquote><div><br>That&#39;s why it&#39;s in &quot;quotes&quot; :) No matter what we do, it will always be wrong for someone somewhere, I&#39;m sure.<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
I am strongly in favor of super.currentmethod(...) if only because<br>that&#39;s closest to how we&#39;ve always done it, and there may even be a<br>use case for callong some *other* super method.</blockquote><div><br>I agree. The big downside of thinking of these things off-line (like in the shower) is that it&#39;s hard to visualize the actual code. The moment I wrote down the three alternatives I&#39;d imagined, I realized &#39;
super.currentmethod()&#39; is the only sane spelling ;)<br></div><br></div>-- <br>Thomas Wouters &lt;<a href="mailto:thomas@python.org">thomas@python.org</a>&gt;<br><br>Hi! I&#39;m a signature-virus-eating-signature-virus-resistant .signature virus! copy me into your .signature file to help me spread!