Scope in objects¶
Scope of variable has been introduice in lesson 2 Scope of variables. Since objects and classes are variables (yes classes too), their scope is defined by the same rules. But hat about the scope of attibutes of objects and classes?
- Attributes are visibles wherever objects and classes are visibles.
- Attributes of an object die when their object dies.
However it is possible to restrict the scope of a variable by making it private i.e. it can be seen only by the object or the class. It is not technically true in Python but it works the same way if we respect few conventions.
Private variables¶
Private variables in a class are variables devated to be used only in the class. By being private they are protected from any outside modification.
Unlike C++, Python has not private methods or private variables. But a convention is to name a variable in a way that specifies if it is weakly or strongly private :
_x
: a variable which starts with an underscore and does not finish with underscore means weakly private i.e. Python will do nothing to protect it but programmers are warned they should not use it outside the class.__x
: a variable which starts with 2 underscores and does not finish with 2 underscores means strongly private i.e. Python will protect it from modification by renaming it. However it can still be modify using its new name.
So when you want a private variable which can be used by child classes use weakly private _
. When you want a private variable used only in its class and not in child classes, use strongly private __
.
class A(object):
def __init__(self):
self._x = 0
self.__y = 1
class B(A):
def __init__(self):
super().__init__()
def print(self):
print(self._x)
print(self.__y) # does not work
b = B()
print(b._x) # it works but it is bad to call a private variable outside its class
b.print()
0 0
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-1-273d0701a1f7> in <module> 14 b = B() 15 print(b._x) # it works but it is bad to call a private variable outside its class ---> 16 b.print() <ipython-input-1-273d0701a1f7> in print(self) 10 def print(self): 11 print(self._x) ---> 12 print(self.__y) # does not work 13 14 b = B() AttributeError: 'B' object has no attribute '_B__y'
Private methods¶
Same applies with methods.
class A(object):
def _f(self):
print('A.f')
def __g(self):
print('A.g')
class B(A):
def f(self):
self._f()
def g(self):
self.__g()
b = B()
b.f()
b.g()
A.f
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-2-17cb3613e146> in <module> 15 b = B() 16 b.f() ---> 17 b.g() <ipython-input-2-17cb3613e146> in g(self) 11 12 def g(self): ---> 13 self.__g() 14 15 b = B() AttributeError: 'B' object has no attribute '_B__g'
On notera que le message d'erreur donne la clef pour accéder à un attribut fortement privée (même si cela n'a pas d'intérêt) : _<nom classe><attribut>
donc
class B(A):
def f(self):
self._f()
def g(self):
self._A__g() # adding class name allows to access to very private attribute (don't do it!)
b = B()
b.f()
b.g()
A.f A.g
La raison pour laquelle c'est possible est la même que la raison pour laquelle il n'y a pas de constante : nous sommes des adultes, si on respecte les conventions tout ira bien.
{{ PreviousNext("02 Inheritance.ipynb", "04 View vs Copy.ipynb")}}