Can someone explain why was I able to set a private variable without using the setter method?
Asked
Active
Viewed 575 times
-2
-
the `.company` attribute did not exist until you set it to facebook, and it is independent from your "private" `.__company` attribute – imochoa Dec 01 '20 at 08:15
-
1First of all Python doesn't really have *private* attributes. Second, you just created a new attribute `company` and didn't change the "private" attribute `__company` – Tomerikoo Dec 01 '20 at 08:30
-
2Please avoid posting images (or worse, links to images) of code or errors. Anything text-based (code and errors) should be posted as text directly in the question itself and formatted properly. You can get more [formatting help here](https://stackoverflow.com/help/formatting). You can also read about [why you shouldn't post images/links of code](//meta.stackoverflow.com/q/285551). – Tomerikoo Dec 01 '20 at 08:31
-
Also, see [What's the pythonic way to use getters and setters?](https://stackoverflow.com/questions/2627002/whats-the-pythonic-way-to-use-getters-and-setters) Also relevant: [What is the meaning of single and double underscore before an object name?](https://stackoverflow.com/questions/1301346/what-is-the-meaning-of-single-and-double-underscore-before-an-object-name) – Tomerikoo Dec 01 '20 at 08:32
-
After assigning to `Facebook` change the `print` to `print(obj2.name, obj2.company, obj2.get_company())` and see what happened – Tomerikoo Dec 01 '20 at 08:40
2 Answers
1
Yes, you can.
Python doesn't really have private members. However, it does some tricky naming things to try and accomplish as such.
When you do have a __member
name, to access it outside, you would use _<ClassName>__<member_name>
Example:
[ttucker@zim stackoverflow]$ cat private.py
class MyClass:
def __init__(self):
self.__private = "initial"
def show(self):
print(self.__private)
private = MyClass()
private.show() # -> "initial"
# Does not actually set the private member,
# but creates a public member with the same name
private.__private = "new"
private.show() # -> "initial"
print(private.__private) # -> "new"
# This actually changes the "private" member.
private._MyClass__private = "new"
private.show() # -> "new"
Execution:
[ttucker@zim stackoverflow]$ python private.py
initial
initial
new
new

Tim
- 2,139
- 13
- 18
-
Please note that it seems the OP is aware of that (the last line is `print(obj2._Employee__company)`) – Tomerikoo Dec 01 '20 at 08:34
-
0
Thanks for @Tomerikoo's answer. I'd like to add something about this.
The key point is that python DOES NOT really have private attributes. Basically, python only changes private attributes' names as format below:
_className__privateAttributeName
So for code in the question, attribute company
is just another new attribute. To verify this, we can use dir(obj2)
to see the details.
>>> dir(obj2)
(Pdb) dir(obj2)
['_Employee__company', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__
', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__n
e__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook_
_', '__weakref__', 'company', 'get_company', 'name', 'set_company']
(Pdb)
As we can see company
and _Employee__company
are just two different attributes.

V Demo
- 151
- 3