【问题标题】:@property not working after adding __slots__添加 __slots__ 后 @property 不起作用
【发布时间】:2017-05-21 18:30:18
【问题描述】:

我怎样才能让 slots 与@property 一起为下面的课程工作。我有几千个导致内存问题的下类实例,所以我添加了插槽

我使用数据创建了实例,然后将位置信息添加到实例中。

添加 slots 后,我的实例创建不起作用,我收到以下错误

AttributeError: 'Host' 对象没有属性 '_location'

class Host(object):
    __slots__ = ['data', 'location']

    def __init__(self, data, location=''):
        self.data = data
        self.location = location

    @property
    def location(self):
        return self._location

    @location.setter
    def location(self, value):
        self._location = value.lower()

    def __repr__(self):
        if self.location == '':
            self.loc = 'Not Found'
        else:
            self.loc = self.location
        return 'Host(name={}, location={})'.format(self.name, self.loc)

【问题讨论】:

  • 因为您没有在__slots__ 中包含支持属性_location。错误消息告诉你这一点。
  • 为什么_locationloc 不在插槽中?
  • self.name 应该在__repr__ 中是什么?
  • @Martijn Pieters - 抱歉,这是复制粘贴。名称与数据为 json
  • @zsh: 可能真的是name = self.data['name']

标签: python properties slots


【解决方案1】:

__slots__ 通过在可以直接访问实例的内存数据结构的类上创建描述符来工作。您正在使用您的 property 对象屏蔽 location 描述符,并且您定义了一个 new 属性 _location,而不是在插槽中。

_location 设为插槽(因为这是您实际存储的属性):

class Host(object):
    __slots__ = ['data', '_location']

location 属性(也是一个描述符对象)然后可以正确分配给 self._location,这是一个由插槽描述符支持的属性。

请注意,您确实不需要__repr__ 中使用self.loc,只需将其设为局部变量即可。您还尝试使用不存在的 self.name 属性;但是不清楚应该是什么值:

def __repr__(self):
    loc = self.location or 'Not Found'
    name = self.data['name']  # or some other expression
    return 'Host(name={}, location={})'.format(name, loc)

【讨论】:

    【解决方案2】:

    __slots__ 的定义应具有基础属性的名称,这些属性将存储您的属性所引用的数据。在下面的示例中,为不应在类外部访问的变量调用name mangling。根据PEP8 online网站,代码和你的类似,没有错误。

    #! /usr/bin/env python3
    def main():
        print(Host('Hello, world!', 'Earth'))
        print(Host('Hello, Xyz!'))
    
    
    class Host:
    
        __slots__ = '__name', '__location'
    
        def __init__(self, name, location=''):
            self.name = name
            self.location = location
    
        def __repr__(self):
            return '{!s}({!r}, {!r})'.format(
                type(self).__name__,
                self.name,
                self.location
            )
    
        @property
        def name(self):
            return self.__name
    
        @name.setter
        def name(self, value):
            self.__name = value
    
        @property
        def location(self):
            return self.__location
    
        @location.setter
        def location(self, value):
            self.__location = value.casefold() if value else 'Not Found'
    
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-12
      • 2014-09-20
      • 2012-04-10
      • 2016-12-02
      • 1970-01-01
      相关资源
      最近更新 更多