如何在Python中封装?

问题描述 投票:11回答:3

这怎么了?从客观和功能的角度来看?

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

做这样的事情实际上有什么问题?

是否有更好的方法可以在Python中实现封装?

python encapsulation
3个回答
42
投票

Python具有封装-您正在类中使用它。

它没有访问控制,例如私有和受保护的属性。但是,在Python中,有一个属性命名约定,通过在属性前面加上一个或两个下划线来表示私有属性,例如:

self._a
self.__a 

单个下划线向类的用户指示,应将属性视为该类的私有属性,不应直接访问该属性。

双下划线表示相同,但​​是,Python会稍微修改属性名称以尝试隐藏它。

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

[在上一个示例中,您可以看到名称已从__a更改为_C__a,尽管仍可以在类中将其作为self.__a进行访问。


1
投票

嗯,Python并没有将封装作为一种“哲学上的”决定,就像我们经常使用鸭子输入一样。就个人而言,我看不到在Python代码中使用私有或受保护参数的意义。

谈到您的代码,它似乎可以与以下getter和setter一起使用:

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

def get_a(self):
    return self.a

如果您对__ getattribute __(self,name)的最后一行进行了以下修改:

return object.__getattribute__(self, name)

但是,您可以使用某种变量保护的概念,如果您在私有变量前加上__,如mhawke所述。另外,Daniel的评论指出了列表参数的局限性。您可以通过在私有列表中添加“私有”和“受保护”来保持受保护的“获取/设置”行为。


0
投票

因此Python 3提供了3个级别的数据访问:

1.public(public,没有特殊语法,publicVariable)

2.protected(受保护,名称开头有一个下划线,_protectedVariable);

3.private(私有,名称开头两个下划线,__ privateVariable)。

所以最后一个称为封装,这意味着限制对对象组件(变量,方法)的访问,因此您可以在类内部定义方法,因此用户可以查看变量甚至更改它,并且如果他想给用户这样的特权,就依赖于编程者,因此,简而言之,实际上它使编程者可以调用可以公开的内容以及内部的内容

私有和公共是基本的,通常被使用,这是一个示例

`

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() 

`

© www.soinside.com 2019 - 2024. All rights reserved.