[Python-ideas] Name mangling and code repetition (with cooperative inheritance use case)
Guido van Rossum
guido at python.org
Tue Apr 9 04:13:02 CEST 2013
On Mon, Apr 8, 2013 at 6:54 PM, Zahari Petkov <zarchaoz at gmail.com> wrote:
> Hello again,
>
> Unfortunatelly, the idea cannot be expressed in the simplest way, since this
> leads to confusion, so I present three short gists and explain the case in this
> email with a bit more words. I am writing it, since I am confident at least it
> will be an interesting read.
>
> All of the three gists present a different implementation of a simple case
> with 4 very simple classes involved.
>
> There are two classes which render instances of types `int` and `float`
> (IntRenderer and FloatRenderer). Imagine similar classes that may render
> any other given type - user classes, a list, etc., but for simplification
> of the case I use only two classes. Each of those classes is instantiated with
> a variable and is called to render this variable into a string.
>
> There is an abstract base class (Renderer), which provides the common
> implementation for all the descendants and leaves the `__call__` to the be
> implemented by the concrete classes.
>
> The last, fourth, class is a dispatcher, which has the sole purpose to pick
> the right renderer, call it and return the result. We prefer many specialized
> classes instead of one big class that may render all types.
>
> The first gist uses composition to achieve that, which would be the
> usual way to do that. The dispatcher iterates, picks the right renderer, calls
> it and returns the value:
>
> https://gist.github.com/majorz/5342257
>
> Cooperative inheritance is however also a great pick for such a use case. In
> this type of implementation if a subclass cannot do the job (render), it will
> delegate the work with super() to the next class in the mro chain. The usage
> of `__private` is justified here,
No. You still misunderstand __private. I fear I cannot help you. Maybe
someone on python-list can explain it better.
> since each subclass in the chain has to
> ensure that some of the used methods are his own internal methods:
>
> https://gist.github.com/majorz/5342262
>
> And here in this second gist we can immediately spot that the __call__ method
> has exactly the same textual representation (although the bytecode and the
> runtime environment are different). If we have hundred such classes, then we
> have to copy/paste this code hundred times, which is not good. (here I define
> the problem trying to solve).
>
> Thus we need to provide more super() powers - the third gist.
> I illustrate the concept with importing from `__future__` a decorator called
> `teleport`, which will make sure that each subclass of a given superclass will
> have its own copy of a given method (which can access its own `__private` and
> `super()`):
>
> https://gist.github.com/majorz/5342271
>
> Personally, I find a similar solution beautiful. Even if it is not perfect
> at least it is a valid attempt to solve a small, but existing problem. Of course
> as an almost ten years user of the language I have to say is something
> extremely rare to find, and especially in Python 3, which is awesome :)
>
> Thanks,
> Zahari
>
> On Tue, Apr 9, 2013 at 2:32 AM, Zahari Petkov <zarchaoz at gmail.com> wrote:
>> Thanks for the answer. Now I realize that I picked a wrong example in
>> the email, and your argument is valid about it. However the code
>> repetition in the gist is a valid example, it cannot be resolved with
>> turning the variables/methods to single underscore mode. I actually
>> almost never use the private convention and I am aware of its purpose
>> and use cases (e.g. __update = update after definition).
>>
>> I will think a bit further for a different not-confusing example and write back.
>>
>> Best,
>> Zahari
>>
>>
>> On Tue, Apr 9, 2013 at 2:15 AM, Guido van Rossum <guido at python.org> wrote:
>>> You are misunderstanding __private. It is for use *within one class*
>>> only. For your purpose you should use single underscore (sometimes
>>> known as "protected").
>>>
>>> On Mon, Apr 8, 2013 at 4:11 PM, Zahari Petkov <zarchaoz at gmail.com> wrote:
>>>> Hello everyone,
>>>>
>>>> In a certain implementation where I was doing some form of dispatch using
>>>> composition, I decided to try out cooperative inheritance with super. However,
>>>> I stumbled at something unexpected - there was nothing wrong with cooperative
>>>> inheritance with super, but the implementation started to have repetative
>>>> code, which could not be easily resolved, because of how name mangling of
>>>> private attribute works.
>>>>
>>>> In short my proposal is for a language feature or mechanism, which will allow
>>>> automatic redefinition of methods through the descendants of a superclass
>>>> during compilation time - at the same time name unmangling is done. In the
>>>> example below I use a decorator - just to illustrate the idea in a very simple
>>>> way:
>>>>
>>>>
>>>> class A:
>>>> __val = 'a'
>>>>
>>>> @propagate_through_descendants
>>>> def print_val(self):
>>>> print(self.__val)
>>>>
>>>>
>>>> class B(A):
>>>> __val = 'b'
>>>>
>>>>
>>>> b = B()
>>>> b.print_val()
>>>>
>>>>
>>>> Please, check the following gist for a bit more concrete example (short and
>>>> working) with cooperative inheritance:
>>>>
>>>> https://gist.github.com/majorz/5341333
>>>>
>>>> The code duplication is very obvious and unavoidable (the two __call__
>>>> methods have exactly the same code, which cannot be moved to the superclass).
>>>> I tried some metaprogramming, but even then it was hard to resolve, since
>>>> name unmangling seems to happen during complilation time as far as I
>>>> understand.
>>>>
>>>> Thanks,
>>>> Zahari
>>>> _______________________________________________
>>>> Python-ideas mailing list
>>>> Python-ideas at python.org
>>>> http://mail.python.org/mailman/listinfo/python-ideas
>>>
>>>
>>>
>>> --
>>> --Guido van Rossum (python.org/~guido)
--
--Guido van Rossum (python.org/~guido)
More information about the Python-ideas
mailing list