How to do encapsulation in Python?

What happened to this? From an objective and functional point of view?

import sys class EncapsulationClass(object): def __init__(self): self.privates = ["__dict__", "privates", "protected", "a"] self.protected = ["b"] print self.privates self.a = 1 self.b = 2 self.c = 3 pass def __getattribute__(self, name): if sys._getframe(1).f_code.co_argcount == 0: if name in self.privates: raise Exception("Access to private attribute \"%s\" is not allowed" % name) else: return object.__getattribute__(self, name) else: return object.__getattribute__(self, name) def __setattr__(self, name, value): if sys._getframe(1).f_code.co_argcount == 0: if name in self.privates: raise Exception("Setting private attribute \"%s\" is not allowed" % name) elif name in self.protected: raise Exception("Setting protected attribute \"%s\" is not allowed" % name) else: return object.__setattr__(self, name, value) else: return object.__setattr__(self, name, value) example = EncapsulationClass() example.a = 10 # Exception: Setting private attribute "a" is not allowed example.b = 10 # Exception: Setting protected attribute "b" is not allowed example.c = 10 # example.c == 10 example.__dict__["privates"] # Exception: Setting protected attribute "b" is not allowed 

What really would be wrong to do something like that?

Is there a better way to achieve encapsulation in Python?

+5
source share
2 answers

Python has encapsulation - you use it in your class.

What he does not have is access control, such as private and protected attributes. However, in Python there is an attribute naming convention for designating private attributes by prefixing an attribute with one or two underscores, for example:

 self._a self.__a 

A single underscore indicates to the class user that the attribute should be considered private to the class and should not be accessed directly.

Double underscores indicate the same thing, but Python will slightly distort the attribute name to try to hide it.

 class C(object): def __init__(self): self.a = 123 # OK to access directly self._a = 123 # should be considered private self.__a = 123 # considered private, name mangled >>> c = C() >>> ca 123 >>> c._a 123 >>> c.__a Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'C' object has no attribute '__a' >>> c._C__a 123 

In the last example, you can see that the name has been changed from __a to _C__a , although it is still available in the class as self.__a .

+32
source

Well, Python does not have encapsulation as a kind of “philosophical” solution, just like we use duck typing. Personally, I see no reason to use private or protected arguments in Python code.

Speaking of your code, it works great with the following getters and setters:

 def set_a(self, v): self.a = v def get_a(self): return self.a 

if you make the following modification to your last line __ getattribute __ (self, name):

 return object.__getattribute__(self, name) 

However, you can use the concept of variable protection if you prefix your personal variables with __, as indicated in mhawke. Plus, Daniel's comment points out the limitation of the arguments of your list. You can save the protected "get / set" behavior by adding "private" and "protected" to your personal list.

+1
source

Source: https://habr.com/ru/post/1204101/


All Articles