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

Bi *_*ico 8 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
Run Code Online (Sandbox Code Playgroud)

他们似乎是不可改变的:

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

TypeError: readonly attribute
Run Code Online (Sandbox Code Playgroud)

上下文,我想创建一个将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
Run Code Online (Sandbox Code Playgroud)

作为一种解决方法,我需要特殊的案例切片:

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
Run Code Online (Sandbox Code Playgroud)

这不是什么大问题,我只想知道背后是否有一些推理.

use*_*ica 9

来自Python bug跟踪器:

补丁#408326旨在分配给d [:]一个错误,其中d是字典.请参阅http://mail.python.org/pipermail/python-list/2001-March/072078.html开始的讨论 .

切片是专门设置为不可用的,所以如果你试图切片分配给一个字典,你会得到一个错误.

不幸的是,邮件列表归档链接看起来不稳定.报价中的链接已经死了,我建议使用的备用链接也已死亡.我能指出的最好的是整个月消息的存档链接; 您可以按Ctrl-F {查找相关的(以及一些误报).


daw*_*awg 7

解决方法是,可以使用__reduce__()支持酸洗切片对象的方法:

>>> s
slice(2, 10, None)
>>> s1=s.__reduce__()
>>> s1
(<class 'slice'>, (2, 10, None))
Run Code Online (Sandbox Code Playgroud)

虽然切片不可散列,但其表示为:

>>> hash(s1)
-5954655800066862195
>>> {s1:'pickled slice'}
{(<class 'slice'>, (2, 10, None)): 'pickled slice'}
Run Code Online (Sandbox Code Playgroud)

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

>>> slice(*s1[1])
slice(2, 10, None)
Run Code Online (Sandbox Code Playgroud)


Abd*_*P M 6

从Python 3.12(2023 年 10 月 2 日发布)开始,slice对象是可哈希的(前提是start、stop和step是可哈希的)。

>>> s = slice(1, 10, 2)
>>> hash(s)
5929446288262424708

>>> s = slice(1, 10, [])
>>> hash(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Run Code Online (Sandbox Code Playgroud)