关于什么可以/不能用作python dict的键,我有点困惑.
dicked = {}
dicked[None] = 'foo' # None ok
dicked[(1,3)] = 'baz' # tuple ok
import sys
dicked[sys] = 'bar' # wow, even a module is ok !
dicked[(1,[3])] = 'qux' # oops, not allowed
Run Code Online (Sandbox Code Playgroud)
所以一个元组是一个不可变的类型,但是如果我在其中隐藏一个列表,那么它就不能成为一个键......难道我不能轻易地隐藏模块中的列表吗?
我有一个模糊的想法,关键是必须"可以",但我只是承认自己对技术细节的无知; 我不知道这里到底发生了什么.如果您尝试使用列表作为键,将哈希作为其内存位置,会出现什么问题?
我已经定义了一个枚举来代表一个"站"的选择; station由唯一的正整数定义,因此我创建了以下枚举,以允许负值表示特殊选择:
enum StationSelector : Printable {
case Nearest
case LastShown
case List
case Specific(Int)
func toInt() -> Int {
switch self {
case .Nearest:
return -1
case .LastShown:
return -2
case .List:
return -3
case .Specific(let stationNum):
return stationNum
}
}
static func fromInt(value:Int) -> StationSelector? {
if value > 0 {
return StationSelector.Specific(value)
}
switch value {
case -1:
return StationSelector.Nearest
case -2:
return StationSelector.LastShown
case -3:
return StationSelector.List
default:
return nil
}
}
var description: String { …
Run Code Online (Sandbox Code Playgroud) 的文档说,一类是可哈希只要它定义__hash__
方法和__eq__
方法.然而:
class X(list):
# read-only interface of `tuple` and `list` should be the same, so reuse tuple.__hash__
__hash__ = tuple.__hash__
x1 = X()
s = {x1} # TypeError: unhashable type: 'X'
Run Code Online (Sandbox Code Playgroud)
什么使得X
不可取消?
请注意,我必须将相同的列表(在正则相等方面)散列为相同的值; 否则,我会违反哈希函数的这个要求:
唯一需要的属性是比较相等的对象具有相同的哈希值
文档会警告不应该在其生命周期内修改可清除对象,当然我不会修改X
创建后的实例.当然,口译员无论如何都不会检查.
我正在尝试创建一个类型的字典,[petInfo : UIImage]()
但我收到了错误Type 'petInfo' does not conform to protocol 'Hashable'
.我的petInfo结构是这样的:
struct petInfo {
var petName: String
var dbName: String
}
Run Code Online (Sandbox Code Playgroud)
所以我想以某种方式使它可以清除,但它的组件都不是一个整数,这是var hashValue: Int
需要的.如果它的字段都不是整数,我怎样才能使它符合协议?dbName
如果我知道它对于所有这个结构的出现都是唯一的,我可以使用吗?
考虑以下代码:
a = {...} # a is an dict with arbitrary contents
b = a.copy()
Run Code Online (Sandbox Code Playgroud)
如何检查Python中的类型是否可变?
假设我有一本字典:
>>> d = {}
Run Code Online (Sandbox Code Playgroud)
它有一个方法clear()
:
>>> d.clear
<built-in method clear of dict object at 0x7f209051c988>
Run Code Online (Sandbox Code Playgroud)
...有一个__hash__
属性:
>>> d.clear.__hash__
<method-wrapper '__hash__' of builtin_function_or_method object at 0x7f2090456288>
Run Code Online (Sandbox Code Playgroud)
......可以调用:
>>> callable(d.clear.__hash__)
True
Run Code Online (Sandbox Code Playgroud)
那么为什么我不能哈希呢?
>>> hash(d.clear)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
Run Code Online (Sandbox Code Playgroud)
注意:我知道dict
对象是不可用的 - 我很好奇为什么这个限制扩展到他们的方法,即使如上所述,他们似乎声称不是这样的?
我有一个方法,其中(以及其他)字典作为参数.该方法是解析字符串,字典提供了一些子字符串的替换,因此它不必是可变的.
这个函数经常被调用,而且在冗余元素上,所以我认为缓存它会提高它的效率.
但是,正如你可能已经猜到的那样,因为它dict
是可变的,因而不能清洗,@functools.lru_cache
所以无法装饰我的功能.那我怎么能克服这个呢?
如果只需要标准的库类和方法,则可以获得奖励积分.理想情况下,如果它存在某种frozendict
标准库,我还没有看到它会成为我的一天.
PS:namedtuple
只有最后的手段,因为它需要大的语法转换.
我的iOS项目一直面临以下问题(这只是警告)。
“ Hashable.hashValue”已作为协议要求弃用;通过实现'hash(into :)'来使类型'ActiveType'与'Hashable'一致
源代码:
public enum ActiveType {
case mention
case hashtag
case url
case custom(pattern: String)
var pattern: String {
switch self {
case .mention: return RegexParser.mentionPattern
case .hashtag: return RegexParser.hashtagPattern
case .url: return RegexParser.urlPattern
case .custom(let regex): return regex
}
}
}
extension ActiveType: Hashable, Equatable {
public var hashValue: Int {
switch self {
case .mention: return -1
case .hashtag: return -2
case .url: return -3
case .custom(let regex): return regex.hashValue
}
} …
Run Code Online (Sandbox Code Playgroud) 我通过大量的教程来理解上述3个术语之间的区别并找到新的术语type erased
容器,现在它让我感到困惑.这引起了很多疑问.
为什么Swift会介绍AnyHashable
?
这3个术语有什么根本区别?
区别Any
和AnyHashable
?
区别Hashable
和AnyHashable
?
何时使用Hashable
以及何时使用AnyHashable
?
最后但最令人困惑的是,type erased
在上下文中术语的含义是什么AnyHashable
?
为了解决这个问题,我一直在玩一个实现Hashable Protocol的自定义结构.我正在尝试查看等效运算符overload(==
)被调用多少次,具体取决于填充a时是否存在哈希冲突Dictionary
.
更新
@matt编写了一个更清晰的自定义结构示例,该结构实现了Hashable协议并显示了调用的频率hashValue
和==
调用次数.我在下面复制他的代码.要查看我的原始示例,请查看编辑历史记录.
struct S : Hashable {
static func ==(lhs:S,rhs:S) -> Bool {
print("called == for", lhs.id, rhs.id)
return lhs.id == rhs.id
}
let id : Int
var hashValue : Int {
print("called hashValue for", self.id)
return self.id
}
init(_ id:Int) {self.id = id}
}
var s = Set<S>()
for i in 1...5 {
print("inserting", i)
s.insert(S(i))
}
Run Code Online (Sandbox Code Playgroud)
这会产生结果:
/*
inserting 1
called …
Run Code Online (Sandbox Code Playgroud) hashable ×10
dictionary ×6
python ×5
swift ×5
python-3.x ×3
swift3 ×2
class ×1
enums ×1
equatable ×1
immutability ×1
instance ×1
ios ×1
list ×1
methods ×1
python-2.x ×1
swift5 ×1
tuples ×1