[Python-ideas] Name mangling and code repetition (with cooperative inheritance use case)

Zahari Petkov zarchaoz at gmail.com
Tue Apr 9 03:54:02 CEST 2013


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, 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)



More information about the Python-ideas mailing list