为什么切片对象在python中不可散列

时间:2015-05-01 02:23:17

标签: python

为什么python中的切片对象不可清除:

>>> s = slice(0, 10)
>>> hash(s)
TypeError                                 Traceback (most recent call last)
<ipython-input-10-bdf9773a0874> in <module>()
----> 1 hash(s)

TypeError: unhashable type

他们似乎是不可改变的:

>>> s.start = 5
TypeError                                 Traceback (most recent call last)
<ipython-input-11-6710992d7b6d> in <module>()
----> 1 s.start = 5

TypeError: readonly attribute

上下文,我想创建一个将python int或slice对象映射到某些值的字典,如下所示:

class Foo:
   def __init__(self):
       self.cache = {}
   def __getitem__(self, idx):
       if idx in self.cache:
           return self.cache[idx]
       else:
           r = random.random()
           self.cache[idx] = r
           return r

作为一种解决方法,我需要特殊情况切片:

class Foo:
   def __init__(self):
       self.cache = {}
   def __getitem__(self, idx):
       if isinstance(idx, slice):
           idx = ("slice", idx.start, idx.stop, idx.step)
       if idx in self.cache:
           return self.cache[idx]
       else:
           r = random.random()
           self.cache[idx] = r
           return r

这不是什么大不了的事,我只想知道背后是否有一些推理。

2 个答案:

答案 0 :(得分:9)

来自Python bug tracker

  

补丁# 408326旨在将d [:]赋值给错误   d是字典。请参阅开始时的讨论   http://mail.python.org/pipermail/python-list/2001-March/072078.html

切片是专门设置为不可用的,因此如果您尝试切片分配给dict,则会出现错误。

不幸的是,邮件列表归档链接看起来不稳定。报价中的链接已经死了,alternate link I suggested using也死了。我能指出的最好的是that entire month of messages的归档链接;您可以使用Ctrl-F查找相关的{(以及一些误报)。

答案 1 :(得分:6)

作为解决方法,您可以使用支持修剪切片对象的__reduce__()方法:

>>> s
slice(2, 10, None)
>>> s1=s.__reduce__()
>>> s1
(<class 'slice'>, (2, 10, None))

虽然切片不可用,但它的表示形式是:

>>> hash(s1)
-5954655800066862195
>>> {s1:'pickled slice'}
{(<class 'slice'>, (2, 10, None)): 'pickled slice'}

你可以轻松地重新构建切片:

>>> slice(*s1[1])
slice(2, 10, None)