2

我有一个类可以跟踪搜索操作期间遇到的错误

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

4 回答 4

1

这一切:

>>> from collections import namedtuple
>>> _SearchError = namedtuple("SearchError", "severity message")
>>> def SearchError(severity=0, message=''):
        return _SearchError(severity, message)
于 2013-04-15T12:37:03.387 回答
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,但我不知道您的对象是否已定义__len__.

或者,甚至更好:

start,stop,step = val.indices(len(self))

同样,在你这样做的情况下a[-1],你没有传入一个切片、0 或 1,所以你点击了else你提出的子句IndexError

于 2013-04-15T12:38:26.003 回答
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)
于 2013-04-15T12:41:40.367 回答
0

我弄乱了代码并找到了以下解决方案。

它使用列表但仅存储变量的名称 - 而不是实际值。此外,它还提供了add添加具有给定名称和值的新变量的方法。新变量也将是可索引的。(我的班级不需要 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']

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

于 2013-04-15T16:50:45.670 回答