Python中如何进行封装?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26216563/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 00:13:29  来源:igfitidea点击:

How to do encapsulation in Python?

pythonencapsulation

提问by will

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?

有没有更好的方法在Python中实现封装?

回答by mhawke

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

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

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:

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

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.

双下划线表示相同,但​​是,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

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

您可以在上一个示例中看到名称已从 更改__a_C__a,尽管它仍然可以在类中作为 访问self.__a

回答by Flavian Hautbois

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.

好吧,Python 没有封装作为一种“哲学”决定,就像我们经常使用鸭子类型一样。我个人认为在 Python 代码中使用私有或受保护的参数没有意义。

Speaking of your code, it seems to work fine with the following getters and setters:

说到您的代码,它似乎可以与以下 getter 和 setter 配合使用:

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

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

return object.__getattribute__(self, name)

However, you canuse 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.

但是,您可以使用某种变量保护的概念,如果您在私有变量前面加上 __,就像 mhawke 提到的那样。另外,丹尼尔的评论指出了您的列表参数的局限性。您可以通过在您的私人列表中添加“private”和“protected”来保持受保护的“get/set”行为。

回答by nemo07

so Python 3 provides 3 levels of data access:

所以 Python 3 提供了 3 个级别的数据访问:

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

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

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

2.protected(protected,名字开头一个下划线,_protectedVariable);

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

3.private(private,名字开头的两个下划线,__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() 

`

`