Name mangling mechanism at module level

Hello, I saw here there exists a name mangling mechanism for class attributes.

Wouldn’t be useful to have a similar mechanism at module level as well ? Let’s say I have a dataclass C, which is used in a final dataclass D. I want to expose only D to clients of this module.

A first idea would be to use triple underscore prefixes for name mangling at module level. For example:

from dataclasses import dataclass, field

@dataclass
class ___C:
    c: int

@dataclass
class D:
    d: ___C = field(default_factory=___C)

I would like to listen other opinions on this.

Thanks in advance

What’s the advantage of mangling the name, versus say just calling it _C?

I like this idea. It will be useful if this would also rise ImportError if someone would like to import such object directly. I am not sure about naming convention, because maybe it could be attached to current convention for mangling (double “_”). If someone uses 2 underscores at the beginning, he would like to set it as “private” in most cases I suppose.

If Python will support that, it will raise also an exception if this object will be accessed directly and that is the most meaningful reason for me. One underscore is just indication, which does not throws any error.

As written, this seems to be useless, since there’s no useful way to construct a D without referencing the “internal” module. But if class C has a default too, then the most logical way to do this would be an inner class.

>>> @dataclass
... class D:
...     @dataclass
...     class __C:
...             c: int = 0
...     d: __C = field(default_factory=__C)
... 
>>> x = D()
>>> x
D(d=D.__C(c=0))

You can use normal double-underscore name mangling if you really need it, and everything works fine.

But more generally: Why do you actually need to hide this? What is insufficient about using a single underscore? Is it a problem that you make the module easier to unit-test?

1 Like

The point of name mangling with double underscores in classes is not to hide things, but to avoid collisions with multiple inheritance. Because the name mangling algorithm is well known, nothing is really hidden.

Module level attributes do not have the same issue with name collisions, so there’s nothing to be gained by name mangling.

And in any event adding the proposed name mangling is a breaking change.

So there’s no reason to add mangling, and the specific proposal here won’t be accepted due to the breaking change.

4 Likes

@ericvsmith I was considering it in the sense @gryznar pointed.

I see. I thought the point was just creating a layer of indirection in the access. But thinking better, it doesn’t make much sense, since the mangling algorithm is well known, as you pointed. Thanks

Do you mean in there sense of making accessing it an error? Python has a long history of not doing that. Note that there’s no way of hiding attribute access, for example.

Yes, I was meaning that.

Got it. Could you point me to more information on why is it like that, please ? Out of curiosity.

I don’t know of any documents describing it. But it’s often referred to as “we’re all consenting adults here”, so maybe google that plus Python.

1 Like

I see. I was wondering if it was something in the language development that turned it not welcome or if it was guided by something more philosophical.

Yes, it’s philosophical.

As an illustration, we have a similar behavior in the Ren’Py engine : names beginnig with two underscores are mangled filename-wise. Since single-underscore names are reserved by the engine itself, the creators can use that to implement privacy for some data not meant to be accessed directly from outside the subsystem they’re creating.
We did not even document what the mangled name results in, which is a clear philosophical divergence from the python ethos.

It’s something that’s not comparable to defining a class inside another class’s body, since the created thing (function, class or even variable) can then be used by any function or class defined in the same file. But then, in our case it’s just a privacy thing, so for reasons previously mentioned it wouldn’t fit in Python.

1 Like