Python takes an interesting approach that mimics the behaviour of statically-typed languages without static typing.
If you have a member that starts with `__` then it gets rewritten. For example's sake let's say that `self.__x` in class `Parent` becomes `__Parent_x`. Also note that because the resulting name starts with `__` as well you can't easily just do this mangling yourself as writing `p.__Parent_x` in class `Other` will result in `p.__Other_Parent_x`. (But you can easily access via something like `getattr(p, "__Parent_x")`). This means that `self.__x == that.__x` will desugar to something like `self.__Parent_x == that.__Parent_x` so you will be able to access privates of other members of the same class. It also means that subclasses won't be able to access private members because `self.__x` will become `self.__Child_x`.
IIUC JavaScript has something similar for `this.#x`. Although this is implemented much more robustly and doesn't rely on unique class names and I believe is actually "secure" as in no other class can gain access. But I am not up-to-date on JS reflection abilities. The code desugars to something like `const X_PROP = new Symbol()` created once-per-class and accessible only to the class itself, then the accesses become something like `this[X_PROP]`.
> IIUC JavaScript has something similar for `this.#x`. Although this is implemented much more robustly and doesn't rely on unique class names and I believe is actually "secure" as in no other class can gain access. But I am not up-to-date on JS reflection abilities. The code desugars to something like `const X_PROP = new Symbol()` created once-per-class and accessible only to the class itself, then the accesses become something like `this[X_PROP]`.
TL;DR it's a language feature, there's no reflection and it's not a syntax sugar for `new Symbol()`. It's actually implemented as a _syntax_ error to access the private member outside the class, which is made possible by using a sigil `#`
If you have a member that starts with `__` then it gets rewritten. For example's sake let's say that `self.__x` in class `Parent` becomes `__Parent_x`. Also note that because the resulting name starts with `__` as well you can't easily just do this mangling yourself as writing `p.__Parent_x` in class `Other` will result in `p.__Other_Parent_x`. (But you can easily access via something like `getattr(p, "__Parent_x")`). This means that `self.__x == that.__x` will desugar to something like `self.__Parent_x == that.__Parent_x` so you will be able to access privates of other members of the same class. It also means that subclasses won't be able to access private members because `self.__x` will become `self.__Child_x`.
IIUC JavaScript has something similar for `this.#x`. Although this is implemented much more robustly and doesn't rely on unique class names and I believe is actually "secure" as in no other class can gain access. But I am not up-to-date on JS reflection abilities. The code desugars to something like `const X_PROP = new Symbol()` created once-per-class and accessible only to the class itself, then the accesses become something like `this[X_PROP]`.