先把各种类型的属性做个对比(自己整理)
是否可修改-hash (不可修改才可index) | 是否有序 | 是否有重复 | 是否可下标 (可查找) | 备注 | ||
tuple | index-value/obj | 不可修改(可hash) | 有序 | 可有重复 | 是 | |
str | 不可修改(可hash) | 有序 | 可有重复 | 是 | 特别的list | |
list | index-value/obj | 可修改 | 有序 | 可有重复 | 是 | |
dict | key:value | 可修改 | 无序 | key无重复 | 是 | 虽然无序,但是有key可查找 |
set | key | 不可修改 | 无序 | 无重复 | 不可 | 无value的dict |
int | | 不可修改 | 有序 | 可有重复 | 不可 | |
float | | 不可修改 | 有序 | 可有重复 | 不可 | |
| | | | | | |
一句话总结
是否可修改/hash
- 不能修改的数据类型
- 不可修改:immutable
- 可hash:hashable
- 不可修改的==可hash==能做为index / key
- 具体包括: int, float, string,tuple
- 可以修改的数据类型
- 可修改:mutable
- 不可hash:inhashable
- 可修改的==不可hash== 不能做为index / key
- 具体包括:list,dict,set
是否可下标subscript able
- 有index /key的就是可下标的
- 可下标就可以查找
是否可嵌套 nest able
- 有index /key的就是可下标的 subscript,就是可嵌套的
哪些数据类型可以嵌套(要看是key的嵌套,还是obj的嵌套)
总结:可修改==不可做index/key,可下标==有index/key==可查找
(1) 各种数据类型,包括数据类型的 index / key (一定不可变) 和value(有的可变 / 有的不可变)
如果是不可变的(可hash),那么只能是 int,float,string,tuple等(不能是list dict)
如果是可变的,可以是各种类型
所以dictA1={[ ]:"jack"} 肯定错误
(2)如果这一层想通过下标查找
这一层如果是可变类型(list 或 dict)或例外 tuple string,那么这一层一定可以 [ ] 这样查找
或者说是,可下标的(list,dict,tuple,string 没例外),那么这一层一定可以 [ ] 这样查找
或者说是,有index/key(list,dict,tuple,string 没例外),那么这一层一定可以 [ ] 这样查找
(3)如果想通过最外层,想通过 嵌套下标 查找
这多层,每层都必须是可变类型(list 或 dict)或例外 tuple string,那么这多层嵌套可以 [ ] 这样查找
或者说是,这多层都是可下标的(list,dict,tuple,string 没例外),那么这多层嵌套可以 [ ] 这样查找
或者说是,这多层都有index/key(list,dict,tuple,string 没例外),那么这多层嵌套可以 [ ] 这样查找
详细的内容
(1)支持下标的类型:tuple ,list ,dict, string (有序index或者有key 就支持下标)
(2)不支持下标的类型:set,int ,float 和各种数字类型
(3)list
list的元素可变,所以可以是任何类型
(4)dict
dict的key的嵌套,因为key不可变
只支持可hash类型:int, float, string ,tuple, 不支持可变的 list ,dict ,set类型
dict的value嵌套,因为value可变
所有类型都可以
但set 等类型还是无法使用下标
(5)set的用法 set={value/obj , value/obj }
set 不支持使用 index (肯定也不支持 key),set 里只有一堆 value/obj
set的元素,需要可hash,只支持 int,float ,string,tuple
同理,string ,int ,float set 因为本身不可修改,元素也是不可修改的
所以也只能是 对应string ,int float tuple 等,不能是 可变类型,list,dict,
一个数据类型,本身不可变 (可hash),那么这个数据类型的元素也不可变
但是特列是tuple,他的元素可以是可变的 list,dict
string的嵌套
虽然string 嵌套没什么意义,但好像这样也算嵌套的。
>>> strC="[1,3,4]aabnb{8,9}"
>>> strC
'[1,3,4]aabnb{8,9}'
>>> strD="abc"'12345'
>>> strD
'abc12345'
LIST嵌套和使用下标
(1) list里的 元素obj 可以是各种类型:
list,tuple,dict,set,string,int,float 等等
(2) list 的 允许嵌套和使用下标,只能是 list, tuple,dict,string
list[ list, tuple,dict]
(3) 如果是string,int,肯定不能往下嵌套了,但是set 也是不能的
而且set int float一样,是不支持 index的
嵌套后支持index的(伪命题,哪一层可下标index得看哪一层本身是否支持)
>>> listB1=[{"name":"jack","age":"15"},{"name":"john","age":"16"}]
>>> listB1[0]["name"]
'jack'
>>> listB1=[("a",1),("b",2)]
>>> listB1[1][1]
2
>>> listB1=[["a",11],["b",22]]
>>> listB1[0][1]
11>>> listC1=["abcde","hhh"]
>>> listC1[0][3]
'd'
嵌套后不支持index的(伪命题,哪一层可下标index得看哪一层本身是否支持)
>>> listB1=[{"apple","pear"},{"red"},{"blue"}]
>>> listB1[0][1]
Traceback (most recent call last):
File "<pyshell#51>", line 1, in <module>
listB1[0][1]
TypeError: 'set' object does not support indexing
>>> >>> listB1=["str1","str2","str3"]
>>> listB2=[11,2,3]
tuple嵌套和使用下标
嵌套后支持index的,同list
>>> tupleA1=((1,2,3),4,5,6)
>>> tupleA1[0][2]
3
>>> tupleA2=(["a","b"],["c"])
>>> tupleA2[0][1]
'b'
>>> tupleA3=({"name":"jack"},{"class":1})
>>> tupleA3[1]["class"]
1
嵌套后不支持index的,还是set 和 int等
>>> tupleA4=({"a","b"},{"aaa"})
>>> tupleA4[0]
{'b', 'a'}
>>> tupleA4[1]
{'aaa'}
>>> tupleA4[0][0]
Traceback (most recent call last):
File "<pyshell#65>", line 1, in <module>
tupleA4[0][0]
TypeError: 'set' object does not support indexing
dict嵌套和使用下标
dict的key的限制
python不支持dict的key为list,dict,set类型,因为list和dict类型是unhashable(不可哈希)的
只支持key是tuple的
>>> dictA1={{"name":"jack","name":"john"}:{"math":90,"phy":95}}
Traceback (most recent call last):
File "<pyshell#67>", line 1, in <module>
dictA1={{"name":"jack","name":"john"}:{"math":90,"phy":95}}
TypeError: unhashable type: 'dict'
>>> dictA2={[1,2,3]:[4,5,6]}
Traceback (most recent call last):
File "<pyshell#68>", line 1, in <module>
dictA2={[1,2,3]:[4,5,6]}
TypeError: unhashable type: 'list'>>> dictA4={{1,2,3}:{7,8,9}}
Traceback (most recent call last):
File "<pyshell#74>", line 1, in <module>
dictA4={{1,2,3}:{7,8,9}}
TypeError: unhashable type: 'set'
只有tuple,string,int,float可以作为key
>>> dictA3={(1,2,3):(4,5,6)}
>>> dictA3[(1,2,3)][1]
5
dict的value的限制
>>> dictB1={"aa":{"a":1,"b":2},"bb":11} #value可以是dict,可以下标查
>>> dictB1["bb"]
11
>>> dictB1["aa"]["a"]
1
>>> dictB2={"aa":[1,2,3],"bb":11} #value可以是list,可以下标查
>>> dictB2["aa"][2]
3
>>> dictB3={(1,2,3):(11,12,13),"bb":11} #key可以是tuple ,value可以是tuple,可以下标查
>>> dictB3[(1,2,3)][1]
12
嵌套后不支持index的
>>> dictB4={"aa":{11,12,13},"bb":11} #value可以是set, 但是不可以下标查
>>> dictB4["aa"][0]
Traceback (most recent call last):
File "<pyshell#85>", line 1, in <module>
dictB4["aa"][0]
TypeError: 'set' object does not support indexing
>>>
set嵌套和--set本身无下标
(1) set 没有下标index
(2)set的 value/obj 还不能是list ,dict ,set等不能hash的类型
也就是说,set 一般元素使用 string,int,float 等,不能嵌套
(3)set唯一可嵌套的,tuple
但是仍然无法有下标,和查找
set无法嵌套 list dict
>>> setA={[1,2,3],[6,5,4]}
Traceback (most recent call last):
File "<pyshell#86>", line 1, in <module>
setA={[1,2,3],[6,5,4]}
TypeError: unhashable type: 'list'>>> setA={{"a":1,"b":2},"aaa"}
Traceback (most recent call last):
File "<pyshell#91>", line 1, in <module>
setA={{"a":1,"b":2},"aaa"}
TypeError: unhashable type: 'dict'
>>>
SET只能嵌套 tuple( 其实就是 set的元素只能是 int float string tuple等)
>>> setA={(1,2,3),(6,5,4)}
>>> setA[1][1]
Traceback (most recent call last):
File "<pyshell#88>", line 1, in <module>
setA[1][1]
TypeError: 'set' object does not support indexing
>>> setA[(1,2,3)][1]
Traceback (most recent call last):
File "<pyshell#89>", line 1, in <module>
setA[(1,2,3)][1]
TypeError: 'set' object is not subscriptable
python里 什么叫不可哈希(可变的不可hash)
作者:三十六_
链接:https://www.jianshu.com/p/bc5195c8c9cb
一个对象能被称为 hashable , 它必须有个 hash 值,这个值在整个生命周期都不会变化,而且必须可以进行相等比较,所以一个对象可哈希,它必须实现__hash__() 与 __eq__() 方法。
Python 的某些链接库在内部需要使用hash值,例如往集合中添加对象时会用__hash__() 方法来获取hash值,看它是否与集合中现有对象的hash值相同,如果相同则会舍去不加入,如果不同,则使用__eq__() 方法比较是否相等,以确定是否需要加入其中。
对于 Python 的内建类型来说,只要是创建之后无法修改的(immutable)类型都是 hashable 如字符串,可变动的都是 unhashable的比如:列表、字典、集合,他们在改变值的同时却没有改变id,无法由地址定位值的唯一性,因而无法哈希。我们自定义的类的实例对象默认也是可哈希的(hashable),而hash值也就是它们的id()。
是否可修改 immutable == hashable ?
immutable:
创建后无法修改的数据类型(obj)都是 hashable的
自定义的类,new实例对象默认也是可哈希的(hashable),而hash值也就是它们的id()。
创建后可修改的数据类型(obj)都是 unhashable的
一个对象能被称为 hashable , 它必须有个 hash 值,这个值在整个生命周期都不会变化,而且必须可以进行相等比较,所以一个对象可哈希,它必须实现__hash__() 与 __eq__() 方法。
列表、字典、集合,他们在改变值的同时却没有改变id,无法由地址定位值的唯一性,因而无法哈希。