【问题标题】:Why are slice objects not hashable in python为什么切片对象在python中不可散列
【发布时间】:2015-07-10 22:13:36
【问题描述】:

为什么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 整数或切片对象映射到某些值,如下所示:

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

这没什么大不了的,我只是想知道这背后是否有一些原因。

【问题讨论】:

标签: python


【解决方案1】:

来自Python bug tracker

补丁# 408326 旨在使分配给 d[:] 出现错误,其中 d 是字典。见讨论开始于 http://mail.python.org/pipermail/python-list/2001-March/072078.html.

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

很遗憾,邮件列表存档链接似乎不稳定。引用中的链接已失效,alternate link I suggested using 也已失效。我能指出的最好的方法是that entire month of messages 的存档链接;您可以 Ctrl-F 为{ 找到相关的(以及一些误报)。

【讨论】:

  • @TadhgMcDonald-Jensen:废话,它是。我想知道为什么。我很确定这些档案不应该被修剪。也许链接真的很不稳定,并且 6 位数的部分在没有警告的情况下更改 - archive.org 在该 URL 的存档中显示 completely unrelated message
【解决方案2】:

作为一种解决方法,您可以使用支持酸洗切片对象的__reduce__() 方法:

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

虽然 slice 不可散列,但它的表示是:

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

您可以轻松地从中重构切片:

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

【讨论】:

    猜你喜欢
    • 2010-12-29
    • 1970-01-01
    • 2011-09-12
    • 2011-05-12
    • 1970-01-01
    • 2021-06-30
    相关资源
    最近更新 更多