使用索引访问实例变量

时间:2013-04-15 12:31:22

标签: python python-2.6

我有一个类跟踪搜索操作中遇到的错误

class SearchError(object): 
    def __init__(self,severity=0,message=''): 
        self.severity = severity
        self.message = message

我的想法是让实例变量可转换。

所以,如果我有

a=SearchError(1,"Fatal Error")

我得到了

>>> a[0]
1
>>> a[1]
'Fatal Error'
>>> a.severity
1
>>> a.message
'Fatal Error'

为此,我在课程中添加了__getitem__方法。现在班级变成了

class SearchError(object): 
    def __init__(self,severity=0,message=''): 
        self.severity = severity
        self.message = message

    def __getitem__(self,val): 
        if isinstance(val,slice): 
            return [self.__getitem__(i) for i in xrange(val.start,val.stop,val.step)]
        elif val==0: 
            return self.severity
        elif val==1: 
            return self.message
        else: 
            raise IndexError

这是我想要的,但在

等情况下失败了
>>> a[:2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 23, in __getitem__
TypeError: an integer is required

甚至

>>> a[-1]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 29, in __getitem__
IndexError

我理解__getitem__的实施是有限的。我需要知道的是 -

  1. 这是使实例变量可转换的方法(不使用列表作为变量容器)吗?
  2. 就索引而言,如何让对象表现得“理智”?

4 个答案:

答案 0 :(得分:1)

这可以做到一切:

>>> from collections import namedtuple
>>> _SearchError = namedtuple("SearchError", "severity message")
>>> def SearchError(severity=0, message=''):
        return _SearchError(severity, message)

答案 1 :(得分:1)

此处的问题是slice个对象默认具有None个值作为属性。因此,a[:2]传入slice(None,2,None)。如果您将其拆分并尝试将其传递给xrange,您将获得TypeError

>>> xrange(None,2,None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an integer is required

试试a[0:2:1],您的代码就可以了。最终,你可以做类似的事情:

val.start = 0 if val.start is None else val.start
val.stop = 2 if val.stop is None else val.stop
val.stop = 2-val.stop if val.stop < 0 else val.stop
val.step = 1 if val.step is None else val.step

将您的切片解析为可用的索引(在一般情况下,最好使用len(self)而不是2,但我不知道您的对象是否已定义{{1 }}

或者,甚至更好:

__len__

同样地,在你执行start,stop,step = val.indices(len(self)) 的情况下,你没有传入切片,0或1,所以你点击了a[-1]子句,你可以在那里提出{{1} }}

答案 2 :(得分:1)

xrange要求其所有参数都是整数,但slice个对象具有None用于未指定的属性。

实施您所追求的目标的最佳方式是使用namedtuple

from collections import namedtuple
class SearchError(namedtuple('SearchError', 'severity message')):
    def __new__(cls, severity=0, message=''):
        return super(SearchError, cls).__new__(cls, severity, message)

答案 3 :(得分:0)

我修改了代码,发现了以下解决方案。

它使用列表但仅存储变量的名称 - 不是实际值。此外,它还提供方法add以添加具有给定名称和值的新变量。新变量也是可索引的。 (我的班级不需要添加功能,但周围很好)

感谢@mgilson在这个方向上轻推我

class SearchError(object): 
    def __init__(self,severity=0,message=''): 
        self.severity = severity
        self.message = message
        self._length = 2
        self._vars_list = ['severity','message',]

    def __getitem__(self,val): 
        if isinstance(val,slice): 
            steps = val.indices(self._length)
            return [self.__getitem__(i) for i in xrange(*steps)]
        elif val < 0: 
            i = self._length + val
            if i < 0: 
                raise IndexError,"Index Out of range for SearchError object"
            else: 
                return self.__getitem__(i)    
        else: 
            try: 
                return getattr(self,self._vars_list[val])
            except IndexError: 
                raise IndexError,"Index Out of range for SearchError object"

    def add(self,var_name,value): 
        self._vars_list.append(var_name)
        self._length += 1
        setattr(self,var_name,value)

结果

>>> a=SearchError(1,"Fatal Error")
>>> a[-1]
'Fatal Error'
>>> a[-2]
1
>>> a[-3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 14, in __getitem__
IndexError: Index Out of range for SearchError object
>>> a[2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 21, in __getitem__
IndexError: Index Out of range for SearchError object
>>> a[1]
'Fatal Error'
>>> a[0]
1
>>> a[:]
[1, 'Fatal Error']
>>> a.add('new_severity',8)
>>> a[:]
[1, 'Fatal Error', 8]
>>> a[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 21, in __getitem__
IndexError: Index Out of range for SearchError object
>>> a[2]
8
>>> a.new_severity
8
>>> a[:3]
[1, 'Fatal Error', 8]
>>> a[:4]
[1, 'Fatal Error', 8]
>>> a[:2]
[1, 'Fatal Error']

据我所见,您需要列表(存储实际变量或其名称)。如果有人有更好的选择,请发布