PEP Idea: Real private attribute
Chris Angelico
rosuav at gmail.com
Sat Aug 28 17:48:22 EDT 2021
On Sun, Aug 29, 2021 at 7:40 AM Mehrzad Saremi <mehrzad.1024 at gmail.com> wrote:
>
> Python currently uses name mangling for double-underscore attributes. Name
> mangling is not an ideal method to avoid name conflicting. There are
> various normal programming patterns that can simply cause name conflicting
> in double-underscore members. A typical example is when a class is
> re-decorated using the same decorator. The decorator can not take
> double-underscore members without name conflicts. For example:
>
> ```
> @custom_decorator("a")
> @custom_decorator("b")
> class C:
> pass
> ```
>
> The `@custom_decorator` wrapper may need to hold private members, but
> Python's current name conflict resolution does not provide any solution and
> the decorator cannot hold private members without applying tricky
> programming methods.
>
> Another example is when a class inherits from a base class of the same name.
>
> ```
> class View:
> """A class representing a view of an object; similar to
> numpy.ndarray.view"""
> pass
>
> class Object:
> class View(View):
> """A view class costumized for objects of type Object"""
> pass
> ```
>
> Again, in this example, class `Object.View` can't take double-underscore
> names without conflicting with `View`'s.
>
> My idea is to introduce real private members (by which I do not mean to be
> inaccessible from outside the class, but to be guaranteed not to conflict
> with other private members of the same object). These private members are
> started with triple underscores and are stored in a separate dictionary
> named `__privs__`. Unlike `__dict__` that takes 'str' keys, `__privs__`
> will be a double layer dictionary that takes 'type' keys in the first
> level, and 'str' keys in the second level.
>
> For example, assume that the user runs the following code:
> ```
> class C:
> def __init__(self, value):
> self.___member = value
>
> c = C("my value")
> ```
>
> On the last line, Python's attribute setter creates a new entry in the
> dictionary with key `C`, adds the value "my value" to a new entry with the
> key 'member'.
>
> The user can then retrieve `c.___member` by invoking the `__privs__`
> dictionary:
>
> ```
> print(c.__privs__[C]['member']) # prints 'my value'
> ```
>
> Note that, unlike class names, class objects are unique and there will not
> be any conflicts. Python classes are hashable and can be dictionary keys.
> Personally, I do not see any disadvantage of using __privs__ over name
> mangling/double-underscores. While name mangling does not truly guarantee
> conflict resolution, __privs__ does.
Not entirely sure how it would know the right type to use (subclassing
makes that tricky), but whatever your definition is, there's nothing
stopping you from doing it yourself. Don't forget that you have
__class__ available if you need to refer to "the class that I'm
lexically inside" (that's how the zero-arg super() function works), so
you might do something like self.__privs__[__class__, "foo"] to refer
to a thing.
ChrisA
More information about the Python-list
mailing list