- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我刚刚在 Python3 中观察到 Set 的一个有趣行为,我想知道为什么。
给定类:
class Tab:
@staticmethod
def set(size):
return set(map(lambda label: Tab(label), range(1, size + 1)));
def __init__(self, label):
self.label = label
self.up = True
def __eq__(self, other):
if not isinstance(other, Tab):
return NotImplemented
return self.label == other.label
def __hash__(self):
return hash(self.label)
def __str__(self):
return str(self.label)
当我调用 Tab.set(9)
时,我得到一组选项卡,当通过以下方式表示为字符串时:
"|%s|" % "|".join([str(tab) for tab in self.tabs])
生成:
|1|2|3|4|5|6|7|8|9|
但是,如果我只修改 __eq__
和 __hash__
以合并 up
属性:
def __eq__(self, other):
if not isinstance(other, Tab):
return NotImplemented
return self.label == other.label and self.up == other.up
def __hash__(self):
return hash((self.label, self.up))
集合的隐式排序发生变化,字符串表示形式变为:
|9|8|7|6|5|4|3|2|1|
我知道集合没有顺序。但是,当静态 set
方法不变时,为什么隐式排序发生了变化,就像以前一样从 1 到 9 创建集合中的每个元素?
而且,我可以做些什么来保留隐式排序,以便我的集合看起来是有序的,就像以前一样? (请注意,更改是由 __hash__
而不是 __eq__
中的更改引起的。)
最佳答案
why did the implicit ordering change
因为 set
被实现为 hashtable在 CPython 中。所以:
set
中项目存储的位置取决于项目的(截断的)哈希值(并且在某种程度上扩展了插入顺序,因为该位置可能已被占用)。__hash__
该项目的方法。如果您遍历 set
,您将逐个槽遍历哈希表(不包括丢失的条目)。因此,通过更改哈希,您可以更改顺序。
在你的例子中,哈希是不同的,因为你改变了 __hash__
方法的实现,所以顺序是不同的:
>>> [hash(tab) for tab in Tab.set(9)] # first code
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [hash(tab) for tab in Tab.set(9)] # second code
[3713072971709512581, 3713088127104978631, 3713071889183430056, 3713087044578896106, 3713083796991988331, 3713082714465905806, 3713085962048483481, 3713084879522400956, 3713081631935493181]
what might I do to preserve the implicit ordering so my set appears to be in order, just as before
如果您希望对它们进行排序,我的建议是不要使用set
- 使用有序集合,仅举一个例子:list
。也有高效的方法remove duplicates from a list and preserving the order .
但如果你想保留 set
并希望它们按 label
属性排序,你也可以使用 sorted
:
sorted(tab.set(9), key=lambda t: t.label)
>>> [str(t) for t in sorted(Tab.set(9), key=lambda t: t.label)]
['1', '2', '3', '4', '5', '6', '7', '8', '9']
注意:这是检查实现细节,可能会因版本而异。 Cython 代码甚至可能不适用于不同的 CPython 版本。 不要从字面上理解它们,也永远不要依赖它们。
如果您对 CPython 的实际实现细节感兴趣,可以使用我在 this answer to "Updating a set while iterating over its elements" 中为 Jupyter 编写的这个 Cython 助手:
%load_ext Cython
%%cython
from cpython cimport PyObject, PyTypeObject
cimport cython
cdef extern from "Python.h":
ctypedef Py_ssize_t Py_hash_t
struct setentry:
PyObject *key
Py_hash_t hash
ctypedef struct PySetObject:
Py_ssize_t ob_refcnt
PyTypeObject *ob_type
Py_ssize_t fill
Py_ssize_t used
Py_ssize_t mask
setentry *table
Py_hash_t hash
Py_ssize_t finger
setentry smalltable[8]
PyObject *weakreflist
cpdef print_set_table(set inp):
cdef PySetObject* innerset = <PySetObject *>inp
for idx in range(innerset.mask+1):
if (innerset.table[idx].key == NULL):
print(idx, '<EMPTY>')
else:
print(idx, innerset.table[idx].hash, <object>innerset.table[idx].key)
这将打印内部哈希表,每一行包含槽号、哈希和存储的项目。
第一种情况:
>>> print_set_table(Tab.set(9))
0 <EMPTY>
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 8 8
9 9 9
10 <EMPTY>
11 <EMPTY>
[...]
30 <EMPTY>
31 <EMPTY>
第二种情况:
>>> print_set_table(Tab.set(9))
0 <EMPTY>
[...]
4 <EMPTY>
5 3713072971709512581 9
6 <EMPTY>
7 3713088127104978631 7
8 3713071889183430056 8
9 <EMPTY>
10 3713087044578896106 6
11 3713083796991988331 3
12 <EMPTY>
13 <EMPTY>
14 3713082714465905806 2
15 <EMPTY>
[...]
24 <EMPTY>
25 3713085962048483481 5
26 <EMPTY>
27 <EMPTY>
28 3713084879522400956 4
29 3713081631935493181 1
30 <EMPTY>
31 <EMPTY>
关于python - 基于 __hash__ 设置更改隐式顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57978737/
这个问题已经有答案了: Is there any way to accept only numeric values in a JTextField? (20 个回答) It's possible i
我使用戴尔 XPS M1710。笔记本电脑的盖子、侧面扬声器和前置扬声器都有灯(3 组灯可以单独调节)和鼠标垫下方的灯。在 BIOS 中,我可以更改这些灯的颜色,至少是每个组。另外,我可以在鼠标垫下打
我知道我可以使用 在 iOS 5 中打开设置应用 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs://"
我有一个 Django 应用程序,我正在尝试为其设置文档。目录结构如下: - doc - project | - manage.py 我已经设置了路径以便 Sphinx 可以看到东西,但是当我尝试使用
我正在使用 768mb ram 运行 centos 5.5。我一直在日志中获取 server reached MaxClients setting, consider raising the MaxC
我在具有以下配置的服务器内运行了 Drupal 安装: StartServers 5 MinSpareServers 5 MaxSpareServers 15 MaxClien
是否可以使用 Microsoft.Web.Administration 包为给定的 location 配置 asp 设置? 我想以编程方式将以下部分添加到本地 IIS applicationHost.
我一直在阅读为 kube-proxy 提供参数的文档,但没有解释应该如何使用这些参数。我使用 az aks create 创建我的集群使用 azure-cli 程序,然后我获得凭据并使用 kubect
我想知道与在 PHP 中使用 setcookie() 函数相比,在客户端通过 JavaScript 设置一些 cookie 是否有任何明显的优势?我能想到的唯一原因是减少一些网络流量(第一次)。但不是
我有一个按钮可以将 body class 设置为 .blackout 我正在使用 js-cookie设置cookie,下面的代码与我的按钮相关联。 $('#boToggle').on('click'
我有一堆自定义的 HTML div。我将其中的 3 存储在具有 slide 类的 div 中。然后,我使用该幻灯片类调用 slick 函数并应用如下设置: $('.slide').slick({
我正在创建一个应该在 Windows 8(桌面)上运行的应用 我需要: 允许用户使用我的应用启动“文件历史记录”。我需要找到打开“文件历史记录”的命令行。 我需要能够显示“文件历史记录”的当前设置。
我刚买了一台新的 MacBook Pro,并尝试在系统中设置 RVM。我安装了 RVM 并将默认设置为 ➜ rvm list default Default Ruby (for new shells)
由于有关 Firestore 中时间戳行为即将发生变化的警告,我正在尝试更改我的应用的初始化代码。 The behavior for Date objects stored in Firestore
在 ICS 中,网络 -> 数据使用设置屏幕中现在有“限制后台数据”设置。 有没有办法以编程方式为我的应用程序设置“限制后台数据”? 或 有没有办法为我的应用程序调出具有选项的“数据使用”设置? 最佳
我正在尝试使用 NextJS 应用程序设置 Jest,目前在 jest.config.js : module.exports = { testPathIgnorePatterns: ["/.n
我最近升级到 FlashDevelop 4,这当然已经将我之前的所有设置恢复到原来的状态。 我遇到的问题是我无法在新设置窗口的哪个位置找到关闭它在方括号、大括号等之前插入的自动空格的选项。 即它会自动
有没有办法以编程方式访问 iPhone/iPod touch 设置? 谢谢。比兰奇 最佳答案 大多数用户设置可以通过读取存储在 /User/Library/Preferences/ 中的属性列表来访问
删除某些值时,我需要选择哪些设置来维护有序队列。我创建了带有自动增量和主键的 id 的表。当我第一次插入值时,没问题。就像 1,2,3,4,5... 当删除某些值时,顺序会发生变化,例如 1,5,3.
我正在尝试设置示例 Symfony2 项目,如此处所示 http://symfony.com/doc/current/quick_tour/the_big_picture.html 在访问 confi
我是一名优秀的程序员,十分优秀!