The absolutely private attribute

Here is the idea of the compiling:

When in a class, if the attributes which are start with “__” but not end with it, python will add “_{classname}” before. I think that changing to the way below can create the really private attribute:

Now the attribute will be addad the header by this way: We add a random function (can use C standard function), and the effect will be:

class ClassHavePrivate:
    def __classprivate(self):
        self.__instanceprivate = ...

    def other_function(self):
        self.__classprivate()

class ClassHavePrivate:
    def other_function(self):
        try:
            getattr(self, randomfunction(id(self), "__classprivate"))()
        except AttributeError:
            getattr(self, randomfunction(id(type(self)), "__classprivate"))()

def the_method(self):
    setattr(self, randomfunction(id(self), "__instanceprivate"), ...)

setattr(ClassHavePrivate, randomfunction(id(ClassHavePrivate), "__classprivate"), the_method)

The randomfunction is:

  1. Set the random seed to the id of the object (ensure that the same input will give same output).
  2. return a string based on the id and the given string.

(To be clear, the function randomfunction won’t be exposure to the user)

By this way, the attribute will be absolutely private. In one program, the visiting of the attribute in the class definition won’t raise “AttributeError” if the “__getattribute__” is normal and the original attribute is existing, while it must raise it out of the class. And the real name of the attribute out of the class is random: due to the id of the objects are different in different process, the result of the string will be also different, and even if the user guesses the real attribute name rightly once, he cannot ensure it will be right in the next object or the next process. What can user do is to use dir to visit it, but if there are many absolutely private attributes, user won’t be able to distinguish which name is right (the sorted will be different due to that the strings are different).

Why do this? The intent of name mangling is to prevent name collisions, not to enforce privacy. Access to internals of other classes is a feature when you need it. I don’t think this idea will gain any traction.

11 Likes

You’re co-opting a feature with one purpose (avoiding accidental collisions - effectively, a type of namespacing) to try to create something with a completely contrary purpose (making things somehow invisible, for whatever benefit that might be). You’ll do MUCH better to start from scratch and try to create a brand new feature.

Though you still have to convince people that this is actually worth doing. I, for one, stopped using the class keyword in C++ a long time ago, preferring to just use struct and letting everything be public. The benefits of hiding things just don’t materialize. It’s far more productive to leave everything public, with a simple namespacing convention (in fact, I just borrowed the Python “leading underscore means private” convention) to show which parts you “should” be accessing.

5 Likes

I would go even a step further than Rosuav:

Name mangling is a clearly documented feature of python. The proposed change would break perfectly valid python code, possibly millions of lines of code out there.

What is the benefit? None.

Why? Because one part of a process cannot “absolutely” hide data from other parts of the process. You said yourself that you still could access the data via dir. In order to find the proper mangeled name (if there are actually several of them in your class), one can use libraries like ctypes to call into every function of the python interpreter. It would be a bit more cumbersome than it would be now, but it would still be possible to break it.

3 Likes

How do we expose randomfunction to the class, so it can create the private attribute, but at the same time not have users be able to use it?

What is just stopping the user from doing id(obj) themselves, and calculating the name?

Also id is not safe for a int that is unique. Some objects may change their I’d when mutated as a new one.

For Python, something like this happens…

>>> i = 1
>>> id(i)
2878592
>>> i += 7
>>> id(i)
2878704

Now if I have a class c: ... and inst = c(), doing inst.x = 1 would name the attribute something like _123456789_x in inst’s namespace. Now, one of our private functions does inst.x += 1, and now, accessing x._123456789_x might raise some error, or worse yet, return a different, but indistinguishable object.

It is because that the original “i” and new “i” are not the same object (you use “=”).

Maybe I will change to three “_” ahead attribute to do it.

If you want to get technical, an object’s ID will never change, even when it’s mutated; but you can’t mutate integers, so augmented assignments on integers will return different objects instead. i += 7 means i = i.__iadd__(7) [1] and it’s up to the object itself whether it mutates (eg lists) or returns a different object (eg ints).


  1. if you want to get even MORE technical, __iadd__ is looked up on the class, not the instance, and there’s slots to look into too, but that’s not relevant to this point ↩︎

5 Likes

Well, yes, but implementation details don’t matter here, when the general thing to take away is, that object IDs are unsafe in that way.

I think a lot of the time people mistaken the idea of real private attributes as a security feature or some sort of otherwise way to obscure access. (It was actually sold as such to me in my college Data Structures class as a security feature for private in C++)

If you’re trying to hide functionality from users, use _ and have an API contract for folks using your library. If users can’t be bothered to follow that contract, you have a bigger people problem on your hands. The ‘general contract’ is _ is private and shouldn’t be used outside of the implementation and its related things.

Even in C++ there are sketchy ways to call private methods from outside the class. If someone wants to do it that badly, there will always be some sort of hacky workaround.

2 Likes
#define private public
#define class struct

Problem solved.

And, how to solve this problem in java:-)

Well, mabye. Conceivably the compiler could lay out the struct
differently depending on whether members are public or private. Don’t
know if there are any compilers that actually do that.

It can be done, although it’s not easy. The Minecraft modding community has found a way. I’m not sure exactly how it works, but it involves inserting hooks into the JIT compiler to change the visibility of methods.

1 Like

I was being a little facetious, that sort of brutal redefinition is liable to cause a lot of problems :slight_smile: Though I highly doubt there’d be reason to lay out a struct differently based on access restrictions. In reality, what I actually do is just… not use class in the first place. No reason to work around access restrictions if you didn’t have access restrictions to start with!

1 Like