什么是pythonic /更快的方式来检查自定义__getitem__方法的“关键”参数是否是切片?

问题描述:

我有一个自定义的序列类型。它本质上是一个列表和一个布尔标志的包装,我希望它能够模拟通常的不可变序列行为。什么是pythonic /更快的方式来检查自定义__getitem__方法的“关键”参数是否是切片?

我的问题是切片。据我所知,在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 

后者看起来更pythonic。它依赖于一个事实,即MyCustomSequenceType.__init__(self, datas, flag)调用LEN(DATAS),它使提高TypeError如果%datasinteger。但是,如果__init__提出TypeError为另一个随机问题它将无法追查。另外http://wiki.cython.org/enhancements/numpy/getitem暗示isinstance更快(实际上更容易优化)。

那我该怎么办?

+0

我不认为'isinstance'在这种情况下是邪恶的。它有足够的非邪恶用途被包含在Python中(与goto不同),这可能就是其中之一。 – 2011-05-19 12:23:43

+3

嗯,它变成了一个蝾螈。 – Evpok 2011-05-19 12:39:38

+0

嗯,我想这是邪恶的。除非你做了一些值得拥有的东西。 – 2011-05-19 16:52:58

你可以看看标准库,并复制那里做了什么。例如,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通过简单地使所述索引或切片通过对基础列表部分地回避问题明确的检查。

+0

确实很明显。那么,我还不习惯Python stdlib组织。下次我会仔细研究一下。谢谢。 – Evpok 2011-05-19 10:46:45

+1

但我宁愿跳过'else:'语句。如果'isinstance(i,slice) 'bumped'True',则第一个'return'语句已经发生,第二个将不会到达。 – Evpok 2011-05-19 10:57:09

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

而且,你不应该直接调用__getitem__ - 使用[]项目符号。

至于我自己,我使用isinstance(key, slice)方法,如果我需要辨别 - slice是一个非常特别的东西,不是一件很容易将是更换另一类型的(想想看 - 如果self.wrapped_listlist,一个slice是将返回除元素或错误以外的唯一类型的对象)。

所以我想最终是这样的:

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

进一步虽然是否需要特殊对待切片考虑;我不知道你的情况是什么,但是当做出一个将来会影响事物的架构决策时,通常考虑一些不同的方法来做同样的事情并评估它们并决定最好的一个(不是那样我自己做的很多 - 我倾向于只是冲过去,然后实施和补丁......)。

+0

嗯,我认为使用'__getitem__'是有道理的,因为使用标准'list'并不意味着限制性,但是当然任何实现它的对象都支持括号表示法,你是对的。 如果'%key'是一个slice,并且'wrapped_list'的一个元素(如果它仅仅是一个单独的索引),那么特别需要处理切片是因为需要返回'MyCustomSequenceType'实例。我想不出有更好的办法去做。 无论如何,谢谢。我的Java开发者赞扬这种解决方案的面向类型。 – Evpok 2011-05-19 10:39:04

+0

另外我编辑问题到'isinstance(key,slice)'以避免潜在读者混淆同样的错误。 – Evpok 2011-05-19 10:52:28