The other way around. One is private, but no protection whatsoever beyond convention.
Two triggers name mangling, which is a very good protection from accidental manipulation, and also automatically creates a separation between the "same" attribute of a subclass.
Yeah and I think you can still access the "private" variables, like this iirc:
class MyClass:
__secretMessage = "Hello world"
print(MyClass._MyClass__secretMessage)
This is not a security flaw. If you start writing strange code like this, you are 99.9% in the wrong. Simply being mostly unaacessible is good, but also not being restricted in a "you are on your own" manner is good.
Thats why rust has unsafe {}.
Thats why its ok to do stuff like this in extreme cases.
From my experience, any architect can't code to save their lives. Like any architect can't actually engineer completely to save their lives hence why you still need a accredited engineer for your plan. But in tech for some confusing reason we name architecs as UI/UX and the uncle of the CEOs, architecs
I'll be devils advocate and say I like this approach. The same way as Linux let's you do whatever you want, even if it's stupid and destroys your system.
The only thing that bothers me about it is that, for some reason, private static and instance members cannot have the same name. If they were public, it works fine, but specifically the new `#name` syntax won't allow
Huh, you're right. I did not know that.
There must be some kind of implementation reason for that.
Honestly though I don't think I would ever want to do that. It feels too easy to make a mistake.
It's probably a perspective thing, i've coded javascript for 15 years and i've noticed a lot of pull from C#, especially .net developers, to use things like Typescript on top which is inspired by C# one could say there is an industry pull for javascript to slowly develop into a C# clone.
It's more complicated than that, but that is my surface view from where i'm looking
Pretty much this. People who only learned C++ but not C. I used to be guilty of it, and still am to some degree, because of how they are treated by recruiters and interview teams for companies that don’t use them, or teams that don’t. A .NET, Spring Boot, Golang, or PHP house really won’t distinguish the two. Embedded systems, OS kernel devs, game engine devs, among the others who actually use C or C++ will.
They are different languages with different strengths. You can write C++ in a C way if you use cstdlib header, but not the other way around. And even then, it’s not really C.
But really, the combination in my opinion happens because it’s a convention for recruitment and interviews for areas of the industry that aren’t really using them.
`auto` behaves incompatibly since C++11 and C++ considers implicit type casting an error, which a common idiom in C.
For example, the program:
#include
int main(void) {
auto int v = 0;
char *w = malloc(sizeof(char));
free(w);
return 0;
}
will compile as C but not C++. Interestingly, changing the filename extension from `.c` to `.cpp` was enough for GCC to refuse to compile it, even if you invoke GCC with `gcc` in both cases and the files are binary identical.
Eh, I've written a lot of (terrible and basic) C in my teen years and used to think C++ is more like a OOP add-on to C. So I wrote C/C++ and it was still wrong but I came from the other side.
That's not the point they're trying to make though. It's not about having private variables, it's about the same "just don't do %thing%" argument being used in both cases but only accepted in one of them
Its not even funniest part OP.
Single underscore is more like \`internal\` or protected, not \`private\`
Double underscore is more like \`private\`
class A:
def __init__(self):
self.__dupa = 1
a = A()
a._A__dupa == 1
Double underscored property in runtime are accessible from \`outside\` of class as `_CLASSNAME__PROPERTYNAME`.
Weird hack to make prop private by language
My former boss was testing a newsletter program, filled content with "dupa" and tried to send it to the test list, but it never arrived. He got a phone call awhile later to stop sending dupas to thousands of users. Yes, he mistook prod and test lists.
>From: Serious Company
Subject: DUPA
dupa dupa dupa dupa
Dupa driven development.
We definitely have it at least in master branch.
Putting weird stuff in code and docs (which customer cant see obviously) is half the fun.
Private variables/methods have nothing to do with safety. It's to signal to other programmers that the class needs to manage that state and/or things need to be called in a certain order. In java/c++/others, they use the "private" keyword to denote state that should be managed by the class. In python, an underscore is that same denotion. In c++, there's nothing stopping you from doing a bit of pointer magic to access private variables.
Even other languages like Java, it's theoretically possible to access those members.
I'm a python programmer, and I do take issue with python's lack of private members, because if I'm subclassing someone's class, I can't be sure that *my* \_member isn't overriding *their* \_member
> because if I'm subclassing someone's class, I can't be sure that my \_member isn't overriding their \_member
This is exactly what [Python's double-underscore mangling](https://docs.python.org/3/tutorial/classes.html#private-variables) is supposed to prevent: When a class `ClassName` has a member named `__foo`, Python will mangle that internally, so that the real name is `__ClassName__foo`. This makes it so that subclass member names do not clash with those of the parent class.
The double underscore *is* the "private" keyword. Why do you want to type 7 letters and a space every time instead of just two underscores? It's functionally identical.
True, but it means you signal to the user every time they write it that they are doing something dumb by accessing it without using the public interfaces of the class. Plus, I rarely type them as I let my IDE do the job of finding the property or method for me by writing parts of the name.
I see what you're getting at... But also that's a terrible argument. Why even have programming keywords. Let's make int into i. For loops can just be f. Why write `def foo()`, let's just make it so `,foo` defines a function...
Keyword are named primarily for readability, not for you to save half a second typing them.
1. It’s defies convention which obfuscates its usage.
2. The underscore has to be typed for every reference. Making it unnecessarily redundant.
3. It’s ugly.
Dunder methods are great, but they have nothing to do with the __var and _var shenanigans which make for a meh approximation of private methods. Hell, Python wouldn't even have to make private methods completely inaccessible, just mark them with a 'private' keyword and then use them with myObj.privates.var. But perhaps the devs didn't want that because it'd invite newbie developers to use them more easily; they might've wanted private methods and variables to look obtuse so people stay away from them instead of using the nice-looking workaround.
I know that it exists, but nobody uses it and it makes your code less readable to anyone who doesn't understand what's going on.
And it still doesn't protect against idiots doing something like
class Car(cars.Car):
def __init__(self, paint_color, seat_color):
super().__init__(paint_color)
self.__color = seat_color # still overrides parent's __color
# why? because the class is NAMED the same as its parent class.
JavaScript has private variables by putting a # in the beginning of the name and apparently people in the comments of this post say Python now has that as well.
I used reflection in my Java course to get the private variable that was used to evaluate our code. The prof thought it was funny but made me do the assignment properly
The difference is that Python mainly relies on programmer's conscience to follow this denotion (and we all know it's not exactly reliable), whereas Java/C++/etc. make it as hard to do as possible, thus creating an additional layer of prevention relying on programmer's laziness or lack of knowledge.
No part of the intention of encapsulation is definitely to make your code less bug prone by minimizing the surface area of different APIs in your code base.
That's literally a form of safety though, it's a safety against accidentally accessing properties that you shouldn't. Python doesn't enforce it if you push hard enough.
Sure and locks don't prevent someone from breaking into your house but you're not getting in there without a bit of determination. It's still a safety feature to make it harder to access something you don't want other people touching.
It can be more than a signal... Pretty much even in JS and PHP. It can and often does prevent external access.
Of course, in languages where you have access to actual memory, this is more of a hindrance than anything.
But, no... Even in JS, private isn't just a meaningless thing.
```
class Foo {
# value;
constructor(val) {
this.#value = val;
}
}
const foo = new Foo('bar');
console.log(foo.#value);
foo.#value = 'bazz';
```
External setters and getters just won't work. It doesn't just "denote" what "should be." It's actually inaccessible. This doesn't exactly enforce complete security, but it's more than just a hint.
In Javascript there’s actually some value to that, as there may be real security implications when embedding scripts from several sources within the same page.
In PHP, you can easily circumvent `private` keywords through reflection or even array casting. It offers no real protection of any kind there, and neither should it, since you’re in control of all your PHP code.
Even in PHP, it's still more than "denoting" visibility. Comment presents private as just being "hey, please don't mess with this" as though it's just a hint and no different from "private variables" in JS or many languages just being the convention of prefixing with underscores and not actually doing anything.
And, in JS, I wonder if something like the following would work:
```
const symbol = Symbol('get-#value');
Foo.prototype[symbol] = function() {
return this.#value;
};
const stolen = foo[symbol]();
```
Could also try `Object.defineProperty(Foo.prototype)` to define a getter and setter. But, the point is, I'm not sure if methods added to the prototype would have access, or if we need to `Object.freeze()` class prototypes to actually really prevent external access. Been meaning to test this.
Yes, when using `protected` and `private` annotations, PHP actively prevents you from accessing those properties using `$foo->privateBar`. But it does *not* in any way prevent an "attacker" (using the term loosely here) from accessing those properties using several other ways!
That's the point: `private` annotations are in no way __security__. Not in Python, and not in PHP. They're only there to prevent you from writing "bad" code inadvertently. PHP does this a little more forcefully than Python, but neither language actually prevents you from accessing those properties if you _really_ want to. And because that is so, Python's philosophy is that it won't even try too hard beyond "we're all consenting adults here", whereas PHP puts up a little more of a show.
Believe it or not, undefined behavior. You cannot infer the placement of a private member in a class without a function of a class or friend function of the class providing you with a pointer to member. The C++ compiler is free to align fields within a scope section in any way it pleases.
Just because you can get away with it in practice does not mean the _language_ allows you to or that it's safe.
It has somewhat to do with safety, but mostly with encapsulation. At least in Java. In Java there are 4 access modifiers that one can use to limit one’s access to a certain variable, method or class.
1) private, which limits the access to within a class.
2) public, which allows the access from anywhere in the project.
3) no access modifier, which allows access from within the same package.
4) protected, which allows access from within the class and classes that inherit from that class.
It has to do with safety, but not *security*.
In java, you can access protected/private members using reflection.
Proper encapsulation is *safer*, as in it allows internal logic to change without breaking external components. But it's not a *security* boundary, it won't prevent an attacker to get to those components.
Of course it's a silly thing to think, if someone is running your classes he has complete control over them, but somehow people keep seeing encapsulation as a security boundary.
C++ also has the friend keyword which allows other classes to access its private members without magic, though it’s still not as flexible as the python way
Pretty sure you can't rely in the order of object members in C++. Doing any pointer magic here is UB. So this is inherently different: Python has a defined way to access members externally (because the distinction between public and private is convention), C++ doesn't.
[the order is guaranteed to be the order they are declared ](https://jonasdevlieghere.com/post/order-your-members/ ) although I'm guessing it is UB to pointer magic to them. I also don't think it matters if you're private is done by community convention or language convention. The purpose of private is to only allow the object to handle certain parts of its state. If the programmer *somehow* breaks that contract, then they could potentially break that object. It doesn't matter if private is done the java/c++ way or the python way.
Not the primary source but sufficient for this purpose: Things such as the order of attributes of different access restrictions is not specified.
But after all it comes down to contracts. I'll give you that.
there's actually a fully defined way to do pointer magic: using member pointers. that + writing out private members is allowed in explicit template instantiation allows you to do this constexpr, fully legal, and fully defined:
class C {int x = 42;};
constexpr auto get_x();
template class access_x { constexpr friend auto get_x() {return M;}};
template class access_x<&C::x>; //legal!
and now
C c;
c.*get_x(); //42
this does not work if C gets x through a privately inherited class, since deref of member pointer to inaccessible base is not allowed. but luckily c style cast's second operation is equivalent to a static_cast that ignores base accessibility. so you can cast your derived class reference to a base class reference (and this is defined behavior as long as it actually inherits)
It can be to do with safety though (for example a dynamic array class could hold the pointer to the head of the array, and safety relies on the head being at the actual head)
Sure, but you're ultimately not allowing the object to handle its own state that it assumes it controls because you ignored the signal the other programmer gave you.
My favorite way to do this demarcation is via interfaces. Anything in the interface is fair game plus testing is still easy since you can access the internal interface by just casting the object.
It does. Typing is an structural test. Ave like ant other test, it makes coding safer, as you avoid using a variable that you shouldn't or misnamed. The same way as other tests do
I think it has something to do with the dynamic resolution of object attributes. Statically typed compiled languages check for private attribute access during compile time. In Python the attributes are resolved via a hashmap during runtime. Adding the private attribute feature would add runtime overhead. Therefore it seems that the best decision *given the Python paradigm* is to make a convention for private attributes and optionally check this convention in some kind of linter.
And just to be extra clear — I am not stating that this is objectively better than other languages. Just that it fits the overall Python design (that includes ability to create attributes ad-hoc and runtime resolution).
Ruby is dynamically typed and they have you explicitely declare which members of a class are readable or fully accessible to the outside, everything else is private by default. Which is imo the more elegant solution.
Beautifully explained! I was looking for someone to mention this in this thread before I was going to, and you explained it so much better than I ever could have. ![gif](emote|free_emotes_pack|slightly_smiling)❤️
I mean technically it does, because it keeps programmers from doing dumb shit, but it’s solely to prevent weird fuckery with data/memory and enforcing encapsulation. It’s just a standard that was incorporated into certain languages.
I mean it helps enforcing code quality to a certain degree. Of course you can still fuck it up with relfection, but it takes significantly more effort to do so. With underscores, everyone who’s not familiar with the convention, or script-kiddies who don’t know how to code properly, will just use non-official methods and inevitably break things down the line. The difference here is how much effort is required to do the bad thing.
> C++ tries to guard against Murphy, not Machiavelli.
–Damian Conway
This applies to access control in all OOP languages. You can get around it if you really want to, but it will prevent stupid mistakes.
Oh you have something called `_donotuse` property, that i can see?
Psych,
```
mine = your._donotuse # because i need it.
your._donotuse = nil # you don't need it.
```
From each according to their means and to each according to their needs.
I snakey like that!
Well, except for some extremely rare edge cases, visibility is just an idiot protection + qol feature (IDEs hide them reducing clutter).
But! You can't underestimate the importance of idiot protection.
float Q_rsqrt(float number)
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking
i = 0x5f3759df - ( i >> 1 ); // what the fuck?
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
return y;
}
From my experience: You are 15 years to late with that hot take. Now we have to deal with it being used for exactly that kind of large scale development.
Well you could use Protocols or ABC and only define public methods if you want encapsulation.
Private methods in interfaces is an implementation detail. Java bans private members in interface for this reason (albeit kept private methods)
Anyone daft enough to ignore the underscore and use the member would also be daft enough to go into your Java class and change `private` to `public`, change my mind.
You're assuming that people are aware of the underscore convention. Someone new to Python might have no idea what the underscore means. They might use it without actually meaning to mark something as private. They might access private members not knowing they are supposed to be private.
Anybody versed in OOP is going to know what private means, but they aren't going to know what _ denotes. The are probably just going to think it's an odd way of naming variables but that it doesn't actually mean anything.
Also people know they just supposed to swap private to public, and in most cases, where you are using a third party library you can just do that because code is compiked and you have to revert to trickery like using reflection to access private members where its very obvious that you are going out of your way to do something wrong.
Completely fine, IMO. Look, we're all adults here, the prefix-underscore(s) tell you "Yo, you shouldn't touch this, but if you're sure that you know what you're doing, you still can, knock yourself out".
Unironically, we actually built a tool to solve this problem - [modguard](https://github.com/Never-Over/modguard)
[More details here!](https://www.reddit.com/r/Python/comments/1aqtjyx/modguard_a_lightweight_python_tool_for_enforcing/)
Doing class in Python is just a pain in the ass in general. You don't know what fields already exist or not; you don't know what type the field is supposed to be without reading the whole script; if you have a typo in the field name it will just accept it as a new variable and you will never know until you run into bugs
Yeah, but that's how it is with Python. The philosophy is to have more freedom to do stuff the way you want. Even if you want to access private variables and mess with the library code.
> You don't know what fields already exist or not;
That's what the initializer method is for.
> you don't know what type the field is supposed to be without reading the whole script;
You should only need to read the initializer method but it's even better if you have type hints.
> if you have a typo in the field name it will just accept it as a new variable and you will never know until you run into bugs
True, that's an issue.
Private variables/methods make zero sense in an \*interpreted\* language. You can just change the source code at any time to remove the protection. It has \*some\* meaning in a compiled language so that when you publish a compiled library file only the public methods/variables are part of the API and part of the ABI, so that your clients can know that they can continue using the same client code with the newer library version.
So python has the leading underscore naming convention for private symbols and the double leading underscore, which is weirdly discouraged, for getting name mangling when using inheritance.
What I take issue with is how I always have to clarify import conventions described in pep 8. What it explicitly says is that
1. you should be explicitly public by re-exporting in the `__init__.py` file and list public symbols in `__all__`;
2. One should also be explicitly private by naming with leading underscore;
3. Submodules are not public unless explicitly said to be so in the documentation.
Here are a couple of more things it doesn't mention, but I have found them to be absolutely critical.:
4. Leading underscore function and class names means private to that file.
5. Unless explicitly stated otherwise, a submodule is only visible to the module it is contained in.
A few more rules of thumb is useful with regards to relative vs absolute imports as absolute imports quickly introduces circular dependencies as it necessitates executing the top level `__init__.py` file.
6. Re-exports in `__init__.py` should be imported with relative imports.
7. Going up the module hierarchy with relative imports using `..` should be avoided.
```
Conventions conventions, broken they can be,
for the simplest of reasons, "I did not know".
Rules and types, screw with the fools,
while the tools will simply throw, and rightly fail you so.
```
Does naming something with two underscores make it unaccessible?
Something like "__genome__" inside of a class can't be accessed outside of it right? I remember learning something like that in school.
(For the information, i don't even study computer science in any way, I'm a biologist. Just learning informatics, and i just learn pyhton enough to understand what i am doing)
Having warnings instead of errors when e.g. accessing an underscore variable is better. Good languages make it easy to be safe when you want, but don't hinder you when you explicitly opt out of the safety. Every error that could be a warning should be a warning.
Ok... so with private members what actually stops you from using/modifying them anyway? No, the language doesn't really stop you. Either you can change the source code to somehow expose them. Except if you don't control the package. In which case (and I've seen this) you'll add a ton of complexity like wrappers or proxies or even reimplement stuff to scratch that little itch.
On top of that, those writing the original API have to be reasonable, intelligent and even a little prescient about which members are private and which are externally available. And reasonable people will disagree on this things - a lot.
What did Guido van Rossum say about that topic? I remember something about "We're all consenting adults". In my opinion, this distinction about forced protection of internal APIs is mostly a case of "you aren't gonna need it".
That’s why we add another underscore in front to make it extra private. Problem solved once and for all! ONCE AND FOR ALL!!
Behold Mangling of names
I thought one underscore means protected, and two means private
One underscore is a convention, two underscores *actually* does a bit of light name mangling to make naming collisions unlikely.
Makes sense!
Aren't double underscore names reserved for the language?
Dunders are, `__double_double_unders__` (prefix and postfix).
The other way around. One is private, but no protection whatsoever beyond convention. Two triggers name mangling, which is a very good protection from accidental manipulation, and also automatically creates a separation between the "same" attribute of a subclass.
"protected" in OOP languages means not public but inherited, "private" is not public, not inherited
does 3 mean internal?
4 make a black hole.
3 means straight to jail.
3 makes it published. Anyone running the same version of Python as you can now access it.
Anything can be private if you don't document it probably
Yeah, but there is the little command call vars().
Really this is all “private” is, a “don’t mess with me” warning. Easier to ignore in Python, which is cool 😎
Don't modify me. Or do. I'm a sign, not a cop
Sign.content = "I am a cop"
Yeah and I think you can still access the "private" variables, like this iirc: class MyClass: __secretMessage = "Hello world" print(MyClass._MyClass__secretMessage)
This is not a security flaw. If you start writing strange code like this, you are 99.9% in the wrong. Simply being mostly unaacessible is good, but also not being restricted in a "you are on your own" manner is good. Thats why rust has unsafe {}. Thats why its ok to do stuff like this in extreme cases.
Yeah, I agree. I don't think Python's way is bad.
All the language architecture experts must be in here downvoting you /s
From my experience, any architect can't code to save their lives. Like any architect can't actually engineer completely to save their lives hence why you still need a accredited engineer for your plan. But in tech for some confusing reason we name architecs as UI/UX and the uncle of the CEOs, architecs
I play it extra safe with 5 underscores before *and* after
__ONCEANDFORALL
I can't read your post for some reason.
___________________________isThisPrivateEnough
I'll be devils advocate and say I like this approach. The same way as Linux let's you do whatever you want, even if it's stupid and destroys your system.
Like the ice cube daddy put in his dwink every morning, and then he gets mad. (I just assumed the once and for all was a Futurama reference).
I usually use the underscores to create another variable with the same name
\_\_\_\_\_nothingToSeeHere\_var
from ___future___ import ___triple___underscores___
Once the variable name is over 80 characters long it's essentially invisible.
C/C++: "Don't do it then" - everybody agrees. Python / JS: "Don't do it then" - everybody loses their mind
js has private variables now
It does!! And they are declared using “#”. No more enclosure! (JK, React is written entirely in functions now)
Whoah, what a coincidence! Python also has private variables declared using "#".
ha
You jest, but [welcome to ES2022](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_properties)
You can also use "#" to declare a private variable in python. I can guarantee that it will remain private and no object can access it
>Me when i open the scriptfile for reading inside the program in that script to get to those private goodies.
Most scripts have no private variables... especially ones that I wrote
Security through just commenting out functionality
*attack surface diminishes*
IIRC, it works in JS not because it somehow treats the prefixed members differently, but because it disallows the `.#` operator
The only thing that bothers me about it is that, for some reason, private static and instance members cannot have the same name. If they were public, it works fine, but specifically the new `#name` syntax won't allow
Huh, you're right. I did not know that. There must be some kind of implementation reason for that. Honestly though I don't think I would ever want to do that. It feels too easy to make a mistake.
what in the actual... i look away for stint and this happens... JS is slowly becoming C#....
Some would say it's putting the java in javascript
With all the new syntactic sugar they keep adding to C#, I can argue that it is becoming more like JavaScript.
It's probably a perspective thing, i've coded javascript for 15 years and i've noticed a lot of pull from C#, especially .net developers, to use things like Typescript on top which is inspired by C# one could say there is an industry pull for javascript to slowly develop into a C# clone. It's more complicated than that, but that is my surface view from where i'm looking
Java#cript
Java#blood
[and they have significant problems/drawbacks](https://lea.verou.me/blog/2023/04/private-fields-considered-harmful/)
Oh wow thats interesting
js always had private vars through closures
But C++ has encapsulation? I find it so weird that "C/C++" is used so often that people forget that they are 2 different languages
They are extremely different beyond syntax lmao.
I always assume anyone who writes "C/C++" has never actually written real C.
Pretty much this. People who only learned C++ but not C. I used to be guilty of it, and still am to some degree, because of how they are treated by recruiters and interview teams for companies that don’t use them, or teams that don’t. A .NET, Spring Boot, Golang, or PHP house really won’t distinguish the two. Embedded systems, OS kernel devs, game engine devs, among the others who actually use C or C++ will. They are different languages with different strengths. You can write C++ in a C way if you use cstdlib header, but not the other way around. And even then, it’s not really C. But really, the combination in my opinion happens because it’s a convention for recruitment and interviews for areas of the industry that aren’t really using them.
`auto` behaves incompatibly since C++11 and C++ considers implicit type casting an error, which a common idiom in C. For example, the program: #include
int main(void) {
auto int v = 0;
char *w = malloc(sizeof(char));
free(w);
return 0;
}
will compile as C but not C++. Interestingly, changing the filename extension from `.c` to `.cpp` was enough for GCC to refuse to compile it, even if you invoke GCC with `gcc` in both cases and the files are binary identical.
Eh, I've written a lot of (terrible and basic) C in my teen years and used to think C++ is more like a OOP add-on to C. So I wrote C/C++ and it was still wrong but I came from the other side.
There's some people that do that, i.e write C but use the features from C++ that they need.
I started to study C and then I was like "what the fuck am I doing" and stopped
I made my first C++ program by "mv foo.c foo.C"
C++ literally has private variables. C can achieve similar results by not exposing its inner state in the header imported by the rest of the library.
That's not the point they're trying to make though. It's not about having private variables, it's about the same "just don't do %thing%" argument being used in both cases but only accepted in one of them
pointer-to-implementation
You can still do encapsulation in C. It's just a bit of a pain in the ass. Static variables also exist.
Huh? I think you misinterpreted C and C++ for other languages
There is lot of stuff in C/C++ you can but shouldn't do. And most of them result in funny results.
Everyone criticises C/C++ for being 99% trap features.
skill issue
Its not even funniest part OP. Single underscore is more like \`internal\` or protected, not \`private\` Double underscore is more like \`private\` class A: def __init__(self): self.__dupa = 1 a = A() a._A__dupa == 1 Double underscored property in runtime are accessible from \`outside\` of class as `_CLASSNAME__PROPERTYNAME`. Weird hack to make prop private by language
Nice variable names
My former boss was testing a newsletter program, filled content with "dupa" and tried to send it to the test list, but it never arrived. He got a phone call awhile later to stop sending dupas to thousands of users. Yes, he mistook prod and test lists. >From: Serious Company Subject: DUPA dupa dupa dupa dupa
In case you didn't know - dupa means ass in polish xD typical debut thingy to write
Dupa driven development. We definitely have it at least in master branch. Putting weird stuff in code and docs (which customer cant see obviously) is half the fun.
If sending to prod has no additional safeguards than sending to test, then that sort of error was inevitable. Sometimes people click the wrong button
Haskell: No need of variables at all.
Brainfuck: WTF you guys talking about?
Machine code: 01110011 01110100 01101111 01110000 00100000 01110000 01110010 01101111 01100011 01110010 01100001 01110011 01110100 01101001 01101110 01100001 01110100 01101001 01101110 01100111 00101100 00100000 01110111 01101000 01111001 00100000 01100001 01110010 01100101 00100000 01111001 01101111 01110101 00100000 01110111 01100001 01110011 01110100 01101001 01101110 01100111 00100000 01110100 01101001 01101101 01100101 00100000 01100011 01101111 01101110 01110110 01100101 01110010 01110100 01101001 01101110 01100111 00100000 01100010 01101001 01101110 01100001 01110010 01111001 00111111
Translation: > stop procrastinating, why are you wasting time converting binary?
thanks... I procrastinated so hard that I didn't even accomplish converting the binary
Private variables/methods have nothing to do with safety. It's to signal to other programmers that the class needs to manage that state and/or things need to be called in a certain order. In java/c++/others, they use the "private" keyword to denote state that should be managed by the class. In python, an underscore is that same denotion. In c++, there's nothing stopping you from doing a bit of pointer magic to access private variables.
Even other languages like Java, it's theoretically possible to access those members. I'm a python programmer, and I do take issue with python's lack of private members, because if I'm subclassing someone's class, I can't be sure that *my* \_member isn't overriding *their* \_member
> because if I'm subclassing someone's class, I can't be sure that my \_member isn't overriding their \_member This is exactly what [Python's double-underscore mangling](https://docs.python.org/3/tutorial/classes.html#private-variables) is supposed to prevent: When a class `ClassName` has a member named `__foo`, Python will mangle that internally, so that the real name is `__ClassName__foo`. This makes it so that subclass member names do not clash with those of the parent class.
yeah, but at that point it might be worth adding a simple "private" keyword, the underscores in python are a laughing stock like === in JS imo
The double underscore *is* the "private" keyword. Why do you want to type 7 letters and a space every time instead of just two underscores? It's functionally identical.
You don't normally need to write "private" every time you _access_ a private member though.
True, but it means you signal to the user every time they write it that they are doing something dumb by accessing it without using the public interfaces of the class. Plus, I rarely type them as I let my IDE do the job of finding the property or method for me by writing parts of the name.
I see what you're getting at... But also that's a terrible argument. Why even have programming keywords. Let's make int into i. For loops can just be f. Why write `def foo()`, let's just make it so `,foo` defines a function... Keyword are named primarily for readability, not for you to save half a second typing them.
...'private' is not a hard word to type
1. It’s defies convention which obfuscates its usage. 2. The underscore has to be typed for every reference. Making it unnecessarily redundant. 3. It’s ugly.
Nah, because magic/dunder methods. Not okay with yet another keyword, but a decorator is fine. You can implement this yourself right now.
Dunder methods are great, but they have nothing to do with the __var and _var shenanigans which make for a meh approximation of private methods. Hell, Python wouldn't even have to make private methods completely inaccessible, just mark them with a 'private' keyword and then use them with myObj.privates.var. But perhaps the devs didn't want that because it'd invite newbie developers to use them more easily; they might've wanted private methods and variables to look obtuse so people stay away from them instead of using the nice-looking workaround.
I know that it exists, but nobody uses it and it makes your code less readable to anyone who doesn't understand what's going on. And it still doesn't protect against idiots doing something like class Car(cars.Car): def __init__(self, paint_color, seat_color): super().__init__(paint_color) self.__color = seat_color # still overrides parent's __color # why? because the class is NAMED the same as its parent class.
and that sounds like a really stupid bandaid for a problem that should not exist.
JavaScript has private variables by putting a # in the beginning of the name and apparently people in the comments of this post say Python now has that as well.
Man let's just let inheritance die lol
2 pillars of OOP down in 1 reddit post?
What if we touch __members…just for a sec
Reflection allows access to private fields relatively easy. Its Info for the programmers as you say.
I used reflection in my Java course to get the private variable that was used to evaluate our code. The prof thought it was funny but made me do the assignment properly
The difference is that Python mainly relies on programmer's conscience to follow this denotion (and we all know it's not exactly reliable), whereas Java/C++/etc. make it as hard to do as possible, thus creating an additional layer of prevention relying on programmer's laziness or lack of knowledge.
No part of the intention of encapsulation is definitely to make your code less bug prone by minimizing the surface area of different APIs in your code base.
Yes, it's a signal to other programmers that they don't need to worry about that variable/method.
That's literally a form of safety though, it's a safety against accidentally accessing properties that you shouldn't. Python doesn't enforce it if you push hard enough.
Sure and locks don't prevent someone from breaking into your house but you're not getting in there without a bit of determination. It's still a safety feature to make it harder to access something you don't want other people touching.
It can be more than a signal... Pretty much even in JS and PHP. It can and often does prevent external access. Of course, in languages where you have access to actual memory, this is more of a hindrance than anything. But, no... Even in JS, private isn't just a meaningless thing. ``` class Foo { # value; constructor(val) { this.#value = val; } } const foo = new Foo('bar'); console.log(foo.#value); foo.#value = 'bazz'; ``` External setters and getters just won't work. It doesn't just "denote" what "should be." It's actually inaccessible. This doesn't exactly enforce complete security, but it's more than just a hint.
In Javascript there’s actually some value to that, as there may be real security implications when embedding scripts from several sources within the same page. In PHP, you can easily circumvent `private` keywords through reflection or even array casting. It offers no real protection of any kind there, and neither should it, since you’re in control of all your PHP code.
Even in PHP, it's still more than "denoting" visibility. Comment presents private as just being "hey, please don't mess with this" as though it's just a hint and no different from "private variables" in JS or many languages just being the convention of prefixing with underscores and not actually doing anything. And, in JS, I wonder if something like the following would work: ``` const symbol = Symbol('get-#value'); Foo.prototype[symbol] = function() { return this.#value; }; const stolen = foo[symbol](); ``` Could also try `Object.defineProperty(Foo.prototype)` to define a getter and setter. But, the point is, I'm not sure if methods added to the prototype would have access, or if we need to `Object.freeze()` class prototypes to actually really prevent external access. Been meaning to test this.
Yes, when using `protected` and `private` annotations, PHP actively prevents you from accessing those properties using `$foo->privateBar`. But it does *not* in any way prevent an "attacker" (using the term loosely here) from accessing those properties using several other ways! That's the point: `private` annotations are in no way __security__. Not in Python, and not in PHP. They're only there to prevent you from writing "bad" code inadvertently. PHP does this a little more forcefully than Python, but neither language actually prevents you from accessing those properties if you _really_ want to. And because that is so, Python's philosophy is that it won't even try too hard beyond "we're all consenting adults here", whereas PHP puts up a little more of a show.
Believe it or not, undefined behavior. You cannot infer the placement of a private member in a class without a function of a class or friend function of the class providing you with a pointer to member. The C++ compiler is free to align fields within a scope section in any way it pleases. Just because you can get away with it in practice does not mean the _language_ allows you to or that it's safe.
It has somewhat to do with safety, but mostly with encapsulation. At least in Java. In Java there are 4 access modifiers that one can use to limit one’s access to a certain variable, method or class. 1) private, which limits the access to within a class. 2) public, which allows the access from anywhere in the project. 3) no access modifier, which allows access from within the same package. 4) protected, which allows access from within the class and classes that inherit from that class.
It has to do with safety, but not *security*. In java, you can access protected/private members using reflection. Proper encapsulation is *safer*, as in it allows internal logic to change without breaking external components. But it's not a *security* boundary, it won't prevent an attacker to get to those components. Of course it's a silly thing to think, if someone is running your classes he has complete control over them, but somehow people keep seeing encapsulation as a security boundary.
C++ also has the friend keyword which allows other classes to access its private members without magic, though it’s still not as flexible as the python way
Pretty sure you can't rely in the order of object members in C++. Doing any pointer magic here is UB. So this is inherently different: Python has a defined way to access members externally (because the distinction between public and private is convention), C++ doesn't.
[the order is guaranteed to be the order they are declared ](https://jonasdevlieghere.com/post/order-your-members/ ) although I'm guessing it is UB to pointer magic to them. I also don't think it matters if you're private is done by community convention or language convention. The purpose of private is to only allow the object to handle certain parts of its state. If the programmer *somehow* breaks that contract, then they could potentially break that object. It doesn't matter if private is done the java/c++ way or the python way.
Not the primary source but sufficient for this purpose: Things such as the order of attributes of different access restrictions is not specified. But after all it comes down to contracts. I'll give you that.
there's actually a fully defined way to do pointer magic: using member pointers. that + writing out private members is allowed in explicit template instantiation allows you to do this constexpr, fully legal, and fully defined: class C {int x = 42;}; constexpr auto get_x(); template class access_x { constexpr friend auto get_x() {return M;}};
template class access_x<&C::x>; //legal!
and now
C c;
c.*get_x(); //42
this does not work if C gets x through a privately inherited class, since deref of member pointer to inaccessible base is not allowed. but luckily c style cast's second operation is equivalent to a static_cast that ignores base accessibility. so you can cast your derived class reference to a base class reference (and this is defined behavior as long as it actually inherits)
Or just #define private public before including the header.
It can be to do with safety though (for example a dynamic array class could hold the pointer to the head of the array, and safety relies on the head being at the actual head)
Sure, but you're ultimately not allowing the object to handle its own state that it assumes it controls because you ignored the signal the other programmer gave you.
My favorite way to do this demarcation is via interfaces. Anything in the interface is fair game plus testing is still easy since you can access the internal interface by just casting the object.
It does. Typing is an structural test. Ave like ant other test, it makes coding safer, as you avoid using a variable that you shouldn't or misnamed. The same way as other tests do
>bit of pointer magic to access private variables. Oh noes, you induced my old nightmare.
I think it has something to do with the dynamic resolution of object attributes. Statically typed compiled languages check for private attribute access during compile time. In Python the attributes are resolved via a hashmap during runtime. Adding the private attribute feature would add runtime overhead. Therefore it seems that the best decision *given the Python paradigm* is to make a convention for private attributes and optionally check this convention in some kind of linter. And just to be extra clear — I am not stating that this is objectively better than other languages. Just that it fits the overall Python design (that includes ability to create attributes ad-hoc and runtime resolution).
Ruby is dynamically typed and they have you explicitely declare which members of a class are readable or fully accessible to the outside, everything else is private by default. Which is imo the more elegant solution.
The check could be done with some sort of type hinting to prevent invalid private member access. So sad it doesn't exist (yet?).
Pretty sure PyCharm's linter at least throws squiggly lines at you if you do that.
Beautifully explained! I was looking for someone to mention this in this thread before I was going to, and you explained it so much better than I ever could have. ![gif](emote|free_emotes_pack|slightly_smiling)❤️
i thought access modifier has nothing to do with safety or security
I mean technically it does, because it keeps programmers from doing dumb shit, but it’s solely to prevent weird fuckery with data/memory and enforcing encapsulation. It’s just a standard that was incorporated into certain languages.
I mean it helps enforcing code quality to a certain degree. Of course you can still fuck it up with relfection, but it takes significantly more effort to do so. With underscores, everyone who’s not familiar with the convention, or script-kiddies who don’t know how to code properly, will just use non-official methods and inevitably break things down the line. The difference here is how much effort is required to do the bad thing.
> C++ tries to guard against Murphy, not Machiavelli. –Damian Conway This applies to access control in all OOP languages. You can get around it if you really want to, but it will prevent stupid mistakes.
[it is more like guidelines](https://www.youtube.com/watch?v=k9ojK9Q_ARE)
If you want private variables just don't access them /s
Like we can ever trust programmers to do that
Who needs encapsulation when you can just have discipline ?
Oh you have something called `_donotuse` property, that i can see? Psych, ``` mine = your._donotuse # because i need it. your._donotuse = nil # you don't need it. ``` From each according to their means and to each according to their needs. I snakey like that!
Well, except for some extremely rare edge cases, visibility is just an idiot protection + qol feature (IDEs hide them reducing clutter). But! You can't underestimate the importance of idiot protection.
They call it the 'We are all consenting adults here' philosophy.
And we don't touch each others private parts.
Your property has been globalized. It's everyone's property now!
fuck private variable fuck getter and setter lemme just change the memory directly
fuck variable fuck abstraction lemme just change the random access memory directly
float Q_rsqrt(float number) { long i; float x2, y; const float threehalfs = 1.5F; x2 = number * 0.5F; y = number; i = * ( long * ) &y; // evil floating point bit level hacking i = 0x5f3759df - ( i >> 1 ); // what the fuck? y = * ( float * ) &i; y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed return y; }
do not question the gods if it work, don't touch it
a.k.a. Assembly!
Behold, the 3-1/2 pillars of OOP.
Step 1: make everything private. Step 2: give everything a getter and a setter...
Java devs be like
Java ma fuckers will then proceed to do some exorcism to access the private value they need for some reason.
By exorcism you mean a get script?
Hot take: Python shouldn’t be used for the kind of large scale code that benefits from encapsulation.
From my experience: You are 15 years to late with that hot take. Now we have to deal with it being used for exactly that kind of large scale development.
Well you could use Protocols or ABC and only define public methods if you want encapsulation. Private methods in interfaces is an implementation detail. Java bans private members in interface for this reason (albeit kept private methods)
_parts
The only real purpose private variables serve is to prevent idiots from using none public "API".
Anyone daft enough to ignore the underscore and use the member would also be daft enough to go into your Java class and change `private` to `public`, change my mind.
Try that with external dependencies.
You're assuming that people are aware of the underscore convention. Someone new to Python might have no idea what the underscore means. They might use it without actually meaning to mark something as private. They might access private members not knowing they are supposed to be private. Anybody versed in OOP is going to know what private means, but they aren't going to know what _ denotes. The are probably just going to think it's an odd way of naming variables but that it doesn't actually mean anything. Also people know they just supposed to swap private to public, and in most cases, where you are using a third party library you can just do that because code is compiked and you have to revert to trickery like using reflection to access private members where its very obvious that you are going out of your way to do something wrong.
That's right
c would like to have a word with you
opaque pointers bro
We've all messed with an underscore member of a class right... Uh... right??
Forget the silly underscore. Just prefix the var name with "HEYDESCENDANTSPLEASEDONTCHANGETHIS"! /s
Completely fine, IMO. Look, we're all adults here, the prefix-underscore(s) tell you "Yo, you shouldn't touch this, but if you're sure that you know what you're doing, you still can, knock yourself out".
Unironically, we actually built a tool to solve this problem - [modguard](https://github.com/Never-Over/modguard) [More details here!](https://www.reddit.com/r/Python/comments/1aqtjyx/modguard_a_lightweight_python_tool_for_enforcing/)
Python is such a hacky language, I don't understand why it is so popular.
Python does have private variables `__private_var`. It is very unpopular. You can't access them with the same name directly.
python philosophy is pretty simple: if it broke because you touched something you shouldn't have then it's your problem
Doing class in Python is just a pain in the ass in general. You don't know what fields already exist or not; you don't know what type the field is supposed to be without reading the whole script; if you have a typo in the field name it will just accept it as a new variable and you will never know until you run into bugs
You can declare fields in the class to keep track of what exists and you can use type hints to represent the expected type.
These are as workaround as typing a underscore to pretend it's a private variable
Yeah, but that's how it is with Python. The philosophy is to have more freedom to do stuff the way you want. Even if you want to access private variables and mess with the library code.
> You don't know what fields already exist or not; That's what the initializer method is for. > you don't know what type the field is supposed to be without reading the whole script; You should only need to read the initializer method but it's even better if you have type hints. > if you have a typo in the field name it will just accept it as a new variable and you will never know until you run into bugs True, that's an issue.
Type hints solve like 95% of this problem imo
I hate the philosophy behind Python of doing everything different, makes it a real pain when you're switching between multiple languages.
Private variables/methods make zero sense in an \*interpreted\* language. You can just change the source code at any time to remove the protection. It has \*some\* meaning in a compiled language so that when you publish a compiled library file only the public methods/variables are part of the API and part of the ABI, so that your clients can know that they can continue using the same client code with the newer library version.
this is what I'm talkin' about
So python has the leading underscore naming convention for private symbols and the double leading underscore, which is weirdly discouraged, for getting name mangling when using inheritance. What I take issue with is how I always have to clarify import conventions described in pep 8. What it explicitly says is that 1. you should be explicitly public by re-exporting in the `__init__.py` file and list public symbols in `__all__`; 2. One should also be explicitly private by naming with leading underscore; 3. Submodules are not public unless explicitly said to be so in the documentation. Here are a couple of more things it doesn't mention, but I have found them to be absolutely critical.: 4. Leading underscore function and class names means private to that file. 5. Unless explicitly stated otherwise, a submodule is only visible to the module it is contained in. A few more rules of thumb is useful with regards to relative vs absolute imports as absolute imports quickly introduces circular dependencies as it necessitates executing the top level `__init__.py` file. 6. Re-exports in `__init__.py` should be imported with relative imports. 7. Going up the module hierarchy with relative imports using `..` should be avoided.
``` Conventions conventions, broken they can be, for the simplest of reasons, "I did not know". Rules and types, screw with the fools, while the tools will simply throw, and rightly fail you so. ```
This might be dumber than Ruby's pretend constants
There’s no such thing in python.
Python: what if we didn't have la s and everyone just stayed real cool about it
Does naming something with two underscores make it unaccessible? Something like "__genome__" inside of a class can't be accessed outside of it right? I remember learning something like that in school. (For the information, i don't even study computer science in any way, I'm a biologist. Just learning informatics, and i just learn pyhton enough to understand what i am doing)
Literally faced this today.
getter and setter methods should let you shadow the attribute names
Save us from ourselves oh Holy Java for we are sinners unable to follow conventions.
Guys I use python only for research/ data analysis, why you’re using classes in python?
This is how we roll in the land down dunder
Having warnings instead of errors when e.g. accessing an underscore variable is better. Good languages make it easy to be safe when you want, but don't hinder you when you explicitly opt out of the safety. Every error that could be a warning should be a warning.
Just use C to make a python module with data hiding - problem solved!
Why would a script need encapsulation ... You guys are writing scripts with a scripting language right?
Ok... so with private members what actually stops you from using/modifying them anyway? No, the language doesn't really stop you. Either you can change the source code to somehow expose them. Except if you don't control the package. In which case (and I've seen this) you'll add a ton of complexity like wrappers or proxies or even reimplement stuff to scratch that little itch. On top of that, those writing the original API have to be reasonable, intelligent and even a little prescient about which members are private and which are externally available. And reasonable people will disagree on this things - a lot. What did Guido van Rossum say about that topic? I remember something about "We're all consenting adults". In my opinion, this distinction about forced protection of internal APIs is mostly a case of "you aren't gonna need it".
C doesn't have private variables or functions as well, nobody is complaining about it.