【问题标题】:Why can't slots be used alongside decorators to enforce encapsulation in Python?为什么插槽不能与装饰器一起使用来强制 Python 中的封装?
【发布时间】:2018-10-25 11:08:09
【问题描述】:

我了解到 Python 中没有严格执行封装。 slots 通常用于更快的属性访问内存节省,如here 所示。但是可以通过使用插槽和装饰器来严格执行封装,如下代码所示:

class GetSet(object):

__slots__ = ["attrval"]
def __init__(self,value):
    self.attrval = value

@property
def var(self):
    #print 'getting the "var" attribute'
    return self.attrval

@var.setter
def var(self,value):
    #print 'setting the "var" attribute'
    self.attrval = value

@var.deleter
def var(self):
    #print 'deleting the "var" attribute'
    self.attrval = None

GetSet 的实例不会有动态变量设置(由于槽),而且 setter 和 getter 方法将调用类中的方法定义。封装不是完全调用了吗?

【问题讨论】:

    标签: python oop decorator encapsulation slots


    【解决方案1】:

    我了解到 Python 中没有严格执行封装。

    因为属性总是公开的。而且无论你做什么都可以联系到他们,即使你使用__成员前缀:

    class GetSet(object):
    
        __slots__ = ["__attrval"]
        def __init__(self,value):
            self.__attrval = value
    
        @property
        def var(self):
            print 'getting the "var" attribute'
            return self.__attrval
    
        @var.setter
        def var(self,value):
            print 'setting the "var" attribute'
            self.__attrval = value
    
        @var.deleter
        def var(self):
            #print 'deleting the "var" attribute'
            self.__attrval = None
    
    obj = GetSet(100)
    # print obj.__attrval # error
    # obj.__attrval = 200 # error
    print obj._GetSet__attrval # got it.
    

    您只需按照惯例进行封装,您使用单个 _ 来向您的库代码用户表明他们是私人成员并且他们尊重您,否则他们的客户端代码可能会在未来面临后果。

    属性很方便,因为它们可以让您完全避免 getter 和 setter。如果您以后需要它们,您可以添加一个属性。

    【讨论】:

    • 您能否解释一下您是如何提出print obj._GetSet__attrval 的,以及“属性很方便,因为它们可以让您完全避免getter 和setter。如果您以后需要它们,您可以添加一个财产。”另外,是否有绕过插槽来动态初始化属性。非常感谢您的回答。
    • 这叫做名字修饰。请阅读部分9.6 Private Variables
    • @P.SaiPrasanth:对于其余的,我的意思是在 Python 中,您通常将成员添加到您知道是公共的类中,但您并不关心。如果后者需要使成员只读,或成员验证,或访问拦截,您将成员名称更改为_membername 以明确不应从外部访问,然后使用属性装饰器添加一个名为membername。客户端代码仍然可以在没有任何更改的情况下工作,并且您会在场景中获得“getter/setter”功能。
    猜你喜欢
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    • 2018-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    相关资源
    最近更新 更多