8

我有一个自定义序列类型。它本质上是一个列表和一个布尔标志的包装器,我希望它能够模拟通常的不可变序列行为。

我的问题是切片。我知道在 Python 3 中实现它的方法是有一个方法,如果是单个索引,__getitem__(key)则返回一个项目,如果是切片对象,则返回一个切片序列。但是我应该如何区分这些情况呢?%key%key

我基本上有两个假设。

sliced_list = self.wrapped_list[key]
if isinstance(key, slice):
    return MyCustomSequenceType(sliced_list, boolean_flag)
return sliced_list

但这是邪恶的,不是吗?或者

sliced_list = self.wrapped_list[key]
try:
    return MyCustomSequenceType(sliced_list, boolean_flag)
except TypeError:
    return sliced_list

后者看起来更蟒蛇。MyCustomSequenceType.__init__(self, datas, flag)它依赖于调用 len(datas)的事实,因此TypeError如果%datasinteger. 但是,如果__init__引发TypeError另一个随机问题,它将无法追踪。还有http://wiki.cython.org/enhancements/numpy/getitem提示isinstance更快(实际上更容易优化)。

那我该怎么办?

4

2 回答 2

10

您可以查看标准库并复制那里所做的工作。例如,calendar.py 有:

def __getitem__(self, i):
    funcs = self._months[i]
    if isinstance(i, slice):
        return [f(self.format) for f in funcs]
    else:
        return funcs(self.format)

它通过简单地将索引或切片传递到基础列表来显示显式检查isinstance 和部分回避问题。

于 2011-05-19T10:12:38.133 回答
2

应该是isinstance(key, slice),不是isinstance(key, "slice")

此外,您不应该__getitem__直接调用 - 使用[]项目符号。

对我自己来说,如果我需要辨别,我使用该方法 -是一个非常特别的东西,而不是很容易被另一种类型替换的东西(想想它 - 如果是 a , a是唯一会返回的对象类型除了元素或错误)。isinstance(key, slice)sliceself.wrapped_listlistslice

所以我最终会这样:

sliced_list = self.wrapped_list[key]
if isinstance(key, slice):
    return MyCustomSequenceType(sliced_list, boolean_flag)
return sliced_list

进一步考虑是否需要对切片进行特殊处理;我不知道您的情况是什么,但是在做出会影响以后事情的架构决策时,通常最好考虑几种不同的方法来做同样的事情并评估它们并决定最好的方法(不是我自己做的很多 - 我倾向于在事后匆忙实施和修补......)。

于 2011-05-19T10:08:49.523 回答