The pythonic way to access a class attribute within the class
I was wondering how do you think is the way to access a class attribute from a function within the class. I haven’t found a reference in PEP8 or a popular question about it. e.g.
class MyClass(object): BAR = 1 def foo(self): # Way A: print(self.BAR) # Way B: print(MyClass.BAR)
Accessing via ´self´ seems reasonable as the attribute is owned by the same class, close reference for obvious same-class reference. On the other hand, accessing via the class name itself is clear as it is static and makes the origin of the use clear and also could be more clear as it is paired with the class’ name.
self.BAR is cool cos you can rename the class and it still works. Drawback is that you cannot use that in static/class methods.
2 Answers 2
When explicity naming the class name, you prevent subclass from overriding your attribute.
On the other hand, using self gives you this flexability. Consider the following code:
class MyClass(object): BAR = 1 def foo(self): # Way A: print(self.BAR) # Way B: print(MyClass.BAR) class SubClass(MyClass): BAR = 2 class SubClass2(MyClass): pass # output >>> a = SubClass() >>> a.foo() 2 1 >>> b = SubClass2() >>> b.foo() 1 1
For reads it doesn’t really matter which you use — self.BAR and MyClass.BAR are syntactically equivalent unless you have a class hierarchy where a subclass redefines the value of BAR .
For writes they are not the same. Writing to self.BAR will effectively create a new variable which is local to the self object instance, so any reads from self.BAR from another object instance will not see the modifications. These can be pretty horrible to debug because it’s not obvious from the code what should happen as it is timing sensitive.
In general for class variables you really should be using MyClass.BAR if you want a specific variable from a specific level in the class hierarchy, or type(self).BAR or self.__class__.BAR if you want something which is inheritance safe. This is specifically and obviously a class variable and avoids the problem outlined above with dynamic aliases popping into existence at runtime. Using self just bakes in some fragility which can be hard to spot in future.
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.
Are you talking about class-level attributes that belong to the class (and all objects) or instance-level attributes defined in a class? I think your question confuses class and object.
7 Answers 7
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 "", line 1, in AttributeError: ClassA instance has no attribute '__double' >>> b.__double Traceback (most recent call last): File "", line 1, in 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 "", line 1, in File "", 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.
How do I set and access attributes of a class? [duplicate]
Your must use self to set and get instance variables. You can set it in the __init__ method. Then your code would be:
class Example(object): def __init__(self): self.itsProblem = "problem" theExample = Example() print(theExample.itsProblem)
But if you want a true class variable, then use the class name directly:
class Example(object): itsProblem = "problem" theExample = Example() print(theExample.itsProblem) print (Example.itsProblem)
But be careful with this one, as theExample.itsProblem is automatically set to be equal to Example.itsProblem , but is not the same variable at all and can be changed independently.
Some explanations
In Python, variables can be created dynamically. Therefore, you can do the following:
class Example(object): pass Example.itsProblem = "problem" e = Example() e.itsSecondProblem = "problem" print Example.itsProblem == e.itsSecondProblem
Therefore, that’s exactly what you do with the previous examples.
Indeed, in Python we use self as this , but it’s a bit more than that. self is the the first argument to any object method because the first argument is always the object reference. This is automatic, whether you call it self or not.
class Example(object): def __init__(self): self.itsProblem = "problem" theExample = Example() print(theExample.itsProblem)
class Example(object): def __init__(my_super_self): my_super_self.itsProblem = "problem" theExample = Example() print(theExample.itsProblem)
It’s exactly the same. The first argument of ANY object method is the current object, we only call it self as a convention. And you add just a variable to this object, the same way you would do it from outside.
Now, about the class variables.
class Example(object): itsProblem = "problem" theExample = Example() print(theExample.itsProblem)
You’ll notice we first set a class variable, then we access an object (instance) variable. We never set this object variable but it works, how is that possible?
Well, Python tries to get first the object variable, but if it can’t find it, will give you the class variable. Warning: the class variable is shared among instances, and the object variable is not.
As a conclusion, never use class variables to set default values to object variables. Use __init__ for that.
Eventually, you will learn that Python classes are instances and therefore objects themselves, which gives new insight to understanding the above. Come back and read this again later, once you realize that.