Python object attributes - methodology for access
Suppose I have a class with some attributes. How is it best (in the Pythonic-OOP) sense to access these attributes ? Just like obj.attr
? Or perhaps write get accessors ?
What are the accepted naming styles for such things ?
Edit: Can you elaborate on the best-practices of naming attributes with a single or double leading underscore ? I see in most modules that a single underscore is used.
If this question has already been asked (and I have a hunch it has, though searching didn't bring results), please point to it - and I will close this one.
Asked by: Blake520 | Posted: 28-01-2022
Answer 1
With regards to the single and double-leading underscores: both indicate the same concept of 'privateness'. That is to say, people will know the attribute (be it a method or a 'normal' data attribute or anything else) is not part of the public API of the object. People will know that to touch it directly is to invite disaster.
On top of that, the double-leading underscore attributes (but not the single-leading underscore attributes) are name-mangled to make accessing them by accident from subclasses or anywhere else outside the current class less likely. You can still access them, but not as trivially. For example:
>>> class ClassA:
... def __init__(self):
... self._single = "Single"
... self.__double = "Double"
... def getSingle(self):
... return self._single
... def getDouble(self):
... return self.__double
...
>>> class ClassB(ClassA):
... def getSingle_B(self):
... return self._single
... def getDouble_B(self):
... return self.__double
...
>>> a = ClassA()
>>> b = ClassB()
You can now trivially access a._single
and b._single
and get the _single
attribute created by ClassA
:
>>> a._single, b._single
('Single', 'Single')
>>> a.getSingle(), b.getSingle(), b.getSingle_B()
('Single', 'Single', 'Single')
But trying to access the __double
attribute on the a
or b
instance directly won't work:
>>> a.__double
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: ClassA instance has no attribute '__double'
>>> b.__double
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: ClassB instance has no attribute '__double'
And though methods defined in ClassA
can get at it directly (when called on either instance):
>>> a.getDouble(), b.getDouble()
('Double', 'Double')
Methods defined on ClassB
can not:
>>> b.getDouble_B()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in getDouble_B
AttributeError: ClassB instance has no attribute '_ClassB__double'
And right in that error you get a hint about what's happening. The __double
attribute name, when accessed inside a class, is being name-mangled to include the name of the class that it is being accessed in. When ClassA
tries to access self.__double
, it actually turns -- at compiletime -- into an access of self._ClassA__double
, and likewise for ClassB
. (If a method in ClassB
were to assign to __double
, not included in the code for brevity, it would therefor not touch ClassA
's __double
but create a new attribute.) There is no other protection of this attribute, so you can still access it directly if you know the right name:
>>> a._ClassA__double, b._ClassA__double
('Double', 'Double')
So why is this a problem?
Well, it's a problem any time you want to inherit and change the behaviour of any code dealing with this attribute. You either have to reimplement everything that touches this double-underscore attribute directly, or you have to guess at the class name and mangle the name manually. The problem gets worse when this double-underscore attribute is actually a method: overriding the method or calling the method in a subclass means doing the name-mangling manually, or reimplementing all the code that calls the method to not use the double-underscore name. Not to mention accessing the attribute dynamically, with getattr()
: you will have to manually mangle there, too.
On the other hand, because the attribute is only trivially rewritten, it offers only superficial 'protection'. Any piece of code can still get at the attribute by manually mangling, although that will make their code dependant on the name of your class, and efforts on your side to refactor your code or rename your class (while still keeping the same user-visible name, a common practice in Python) would needlessly break their code. They can also 'trick' Python into doing the name-mangling for them by naming their class the same as yours: notice how there is no module name included in the mangled attribute name. And lastly, the double-underscore attribute is still visible in all attribute lists and all forms of introspection that don't take care to skip attributes starting with a (single) underscore.
So, if you use double-underscore names, use them exceedingly sparingly, as they can turn out quite inconvenient, and never use them for methods or anything else a subclass may ever want to reimplement, override or access directly. And realize that double-leading underscore name-mangling offers no real protection. In the end, using a single leading underscore wins you just as much and gives you less (potential, future) pain. Use a single leading underscore.
Answered by: Owen669 | Posted: 01-03-2022Answer 2
The generally accepted way of doing things is just using simple attributes, like so
>>> class MyClass:
... myAttribute = 0
...
>>> c = MyClass()
>>> c.myAttribute
0
>>> c.myAttribute = 1
>>> c.myAttribute
1
If you do find yourself needing to be able to write getters and setters, then what you want to look for is "python class properties" and Ryan Tomayko's article on Getters/Setters/Fuxors is a great place to start (albeit a little long)
Answered by: Adrian905 | Posted: 01-03-2022Answer 3
Edit: Can you elaborate on the best-practices of naming attributes with a single or double leading underscore ? I see in most modules that a single underscore is used.
Single underscore doesn't mean anything special to python, it is just best practice, to tell "hey you probably don't want to access this unless you know what you are doing". Double underscore however makes python mangle the name internally making it accessible only from the class where it is defined.
Double leading AND trailing underscore denotes a special function, such as __add__
which is called when using the + operator.
Read more in PEP 8, especially the "Naming Conventions" section.
Answered by: Ada630 | Posted: 01-03-2022Answer 4
I think most just access them directly, no need for get/set methods.
>>> class myclass:
... x = 'hello'
...
>>>
>>> class_inst = myclass()
>>> class_inst.x
'hello'
>>> class_inst.x = 'world'
>>> class_inst.x
'world'
BTW, you can use the dir() function to see what attributes/methods are attached to your instance:
>>> dir(class_inst)
['__doc__', '__module__', 'x']
Two leading underbars, "__" are used to make a attribute or function private. For other conventions refer to PEP 08: http://www.python.org/dev/peps/pep-0008/
Answered by: Arthur368 | Posted: 01-03-2022Answer 5
Python does not need to define accessors right from the beginning, since converting attributes into properties is quick and painless. See the following for a vivid demonstration:
Answered by: Elise211 | Posted: 01-03-2022Answer 6
There is no real point of doing getter/setters in python, you can't protect stuff anyway and if you need to execute some extra code when getting/setting the property look at the property() builtin (python -c 'help(property)')
Answered by: Luke698 | Posted: 01-03-2022Answer 7
Some people use getters and setters. Depending on which coding style you use you can name them getSpam and seteggs. But you can also make you attributes readonly or assign only. That's a bit awkward to do. One way is overriding the
> __getattr__
and
> __setattr__
methods.
Edit:
While my answer is still true, it's not right, as I came to realize. There are better ways to make accessors in python and are not very awkward.
Answered by: Chester629 | Posted: 01-03-2022Similar questions
How do I get an overview and a methodology for programming in Python
I've started to learn Python and programming from scratch. I have not programmed before so it's a new experience. I do seem to grasp most of the concepts, from variables to definitions and modules. I still need to learn a lot more about what the different libraries and modules do and also I lack knowledge on OOP and classes in Python.
I see people who just program in Python like that's all they have ever done and I...
python - How do I migrate my current deployment methodology to one using Docker?
This is going to be a bit of along question, so be forewarned.
The short version:
Our current deployment system uses Fabric and Git to deploy a Python web application and supporting parts. The system works well but after spending 2 weeks working to extend it I realised I was essentially trying to re-invenˆt the Docker wheel. I thus decided to look at re-working things to use Docker. Howeve...
python - Error handling methodology
In C, if I'm not wrong, the main function returns 0 if no errors occurred, and something different from 0 if an error occurs.
Is is appropriate to do the same in Python (as long as a function does not have to return any specific value but one to indicate the success/failure); or instead just handle exceptions?
python - Which test methodology is best for testing the whole Django REST application?
Closed. This question is opinion-based. It is not c...
python - New string formatting methodology
I'm working through "Python 101" by Mathew Driscoll and have ran into an issue when I try this.
>>> print("%(lang)s is fun!" % {"lang":"python"})
I understand i'm trying to use the Python dictionary here with lang being a "key value pair"
All i'm doing is copying whats in the book but, the book has been out awhile and I'm using the newest version of Python.
This is the err...
stanford nlp - what does the methodology in picture indicates? Python programming
I am trying to implement the process as shown in the below image for text summarization:
I have understood that the second step is the generating the dependency graph using the Stanford Parser. Here is the code:
from nltk.parse.stanford import Stanfo...
Kalman filter in R with Pykalman (Python) methodology
Good afternoon!
I have a code in Python using Pykalman (https://pykalman.github.io/) where I create and I do not specify any parameters for the Kalman filter, just the number of dimensions of my observations. Initial values are initiated automatically (for example identity for the transition matrix) and then using EM algorithm, parameters of the Ka...
python - What methodology is best suited for Regression from text data?
I have a bunch of sentences each associated with a numerical performance value.
I would like to do two things:
Based on a new sentence predict performance
Find out which words have the highest correlation with a high score
What's the best way to extract features from sentences? Can someone advise me one which model is best suited for the above and is available in Sklearn?
...
python - Why arr[idx,:] (for 2D arrays) considered a good methodology
A lot of python snippets using numpy are using arr[idx,:] notation when the array is 2D.
e.g
gradPred = -outputVectors[target,:] * (1 - r_W_prob[target])
gradPred += np.dot(r_W_prob[negative_samples], outputVectors[negative_samples, :])
I have two followup questions:
a) Is there a difference betwenn outputVectors[target,:] and just ...
python - In SKLearn Logistic Regression, class = Balanced helps run the model with imbalanced data? what methodology does this option use
Having read about random under sampling, random over sampling and SMOTE, I am trying to understand what methodology is used by the default implement in SKlearn package for Logistic Regression or Random Forest.
I have checked documentation here
Still can't find your answer? Check out these communities...
PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python