How to do encapsulation in Python?

社会主义新天地 提交于 2019-12-03 07:01:17

问题


What's wrong with this? From objective, and functional standpoints?

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 would actually be wrong with doing something like this?

Is there any better way to achieve encapsulation in Python?


回答1:


Python has encapsulation - you are using it in your class.

What it doesn't have is access control such as private and protected attributes. However, in Python, there is an attribute naming convention to denote private attributes by prefixing the attribute with one or two underscores, e.g:

self._a
self.__a 

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

A double underscore indicates the same, however, Python will mangle the attribute name somewhat to attempt 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()
>>> c.a
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

You can see in the last example that the name was changed from __a to _C__a, although it is still accessible within the class as self.__a.




回答2:


Well, Python does not have encapsulation as a sort of "philosophical" decision, in the same way that we use duck typing a lot. Personally I don't see the point of using private or protected arguments in a Python code.

Speaking of your code, it seems to work fine 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 of __ getattribute __(self, name):

return object.__getattribute__(self, name)

However, you can use sort of a notion of variable-protecting, if you prefix your private variables with __, as mhawke mentioned. Plus, Daniel's comment points out a limitation of your list arguments. You could keep the protected "get/set" behaviour by adding "private" and "protected"in your private list.




回答3:


so Python 3 provides 3 levels of data access:

1.public ( public, there is no special syntax, publicVariable)

2.protected ( protected, one underscore at the beginning of the name, _protectedVariable);

3.private ( private, two underscores at the beginning of the name, __privateVariable).

so the last one is called encapsulation , which means restricting access to the components of an object (variables,methods) ,tho u can define methods inside of the class , so the user can either see the variable or even change it ,and that rely on the progammer if he wanna give the user such privilges , so in brief it actually gives the progammer the to call what can be public and what is internal

the private and the public are the basic and typically used ,and here is an example

`

class phone:
    name="sony" #this variable is public
    __number= 201090943929 #this is private one ,and also my actual number heheheheeh boii
    def print_name(self): #this is public method
        print ('my phone name is:', self.name)
    def __print_number(self): #and private method
        print (self.__number)
#actually we(the programmer not the user)-while writing the code- can give the user the user the authority to only 
#see the value of the variable ,even to modify it by defining a metod inside the class 
    def print_private_number(self):
        return self.__number
    def modify_private_number(self,newNumber):
        self.__number=newNumber
        print(newNumber)
#now u can both prnt and modify the mumber with only the following methods

my_phone=phone()
my_phone.print_name() #now i called the public function , and cam simply print it as it's public (can be accessed)
print (my_phone.name) #same as here with variable
#Now if we tried to retrive private data ,or run private method
#its gonna end up with an error 
#print (my_phone.__number)
#my_phone.__print_number()

print (my_phone.print_private_number())
my_phone.modify_private_number(5)
#so what if the programmer didnt allow us to see the number 
#is that the end of the road ? nah ,we still can crack the system and both read and modify the private variables n functions
#hmmm am not gonna call it crack coz the langauage itself provides the programmer with 
#syntatic tool that circumvent encapsulation
print (my_phone._phone__number) 
#my_phone._phone__print_name() 

`



来源:https://stackoverflow.com/questions/26216563/how-to-do-encapsulation-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!