PythonI / O Advanced study notes _5.python the set and dict

Preface:

I have always felt for me to learn the system is not taboo. In this part of the class on a custom sequence are linked.

Previous through comparative range of protocols and features understand some sequence of classes, and the contents of some list. This is more specific to the set and two sequences dict class.

In order to understand the specific application python sequence class. (This is relatively simple) (Specific feel easier to understand than the abstract, but must learn to think abstract to concrete objects to express that extract common)

content:

1.dict sequence types and inheritance in the abc

2.dict achieve a common method

3. Can I inherited this sequence dict class?

4.set and frozenset

And dict the principle 5.set

==============

 

1.dict sequence types and inheritance in the abc

In collection.abc dict in fact it belongs MutableMapping (variable mapping) type.

Keep up articles of variable sequence analysis of the same class inheritance, MutableMapping inherited some Mapping functionality and added some variable features,

Mapping inherited Collection. The next chapter of inheritance and on the same.

 

2.dict achieve a common method

If the pycharm, or with ctrl + b can skip the python dict definition.

Common:

a = {"1":{"a":"aa"},
     "2":{"b":"bb"}}

# 清空字典
a.clear()

# 浅拷贝字典 浅拷贝虽然可以正常赋值,但是如果 my_dopy_dict 中的值进行了改变,则 a 中的值也会进行对应的改变
my_dopy_dict = a.copy()

# 深拷贝 深拷贝则是实实在在的在内存当中声明了一个新的变量
import copy
new_dict = copy.deepcopy(a)

# get函数 dict.get(要查找的key,如果没找到对应key的内容返回的数据)
print(a.get("3",{1:"3"})) # {1: '3'}

# dict.fromkeys() 函数用于创建一个新字典,以序列 seq 中元素做字典的键 seq可以是可迭代的,value 为字典所有键对应的初始值。
my_list = [1, 2, 3]
my_new_dict = dict.fromkeys(my_list, {"222":"3434"}) #{1: {'222': '3434'}, 2: {'222': '3434'}, 3: {'222': '3434'}}

# setdefault() 函数和 get()方法 类似,
# 如果键不存在于字典中,将会添加键并将值设为默认值。
# 如果存在,则将会返回该key对应的value
a.setdefault("3", "cc") # a= {'1': {'a': 'aa'}, '2': {'b': 'bb'}, '3': 'cc'}
print(a.setdefault("2", "cc")) # 返回{'b': 'bb'}

# update() 函数把字典dict2的键/值对更新到dict里。
# 如果字典b中有与a相同的key,则会把a中的key对应的value进行更新
# 如果字典b中有a中没有的key,则a会将未有的key与value添加进去
b = {"3": "cc", "2": "dd"}
a.update(b)
print(a) # {'1': {'a': 'aa'}, '2': 'dd', '3': 'cc'}

 

3.我可不可以继承dict这种序列类?(dict的子类)

a.如果我偷懒想实现dict这种类型,能不能直接继承这种序列类呢?同理list是否可以?

例:继承dict,并且重写设置dict key的value时调用的魔法函数,使其值变为2倍

class Mydict(dict):
    def __setitem__(self, key, value):
        super().__setitem__(key, value*2)

a=Mydict(b=1)
print(a)

a['b']=1
print(a)

输出:

可以发现,原来同样功能和效果的,我们重写方法后,第一种方法去设置key的value值这一操作并没有调用我们重写的方法。

所以并不建议去继承python的这种序列类。

 

b.有没有什么办法我实在想继承?

python里专门给了个UserDict类,可以实现想要的继承Dict类的效果

from collections import UserDict
class Mydict(UserDict):
    def __setitem__(self, key, value):
        super().__setitem__(key, value*2)

mydict = Mydict(one = 1) # {'one': 2} 调用__setitem__这个魔法函数
mydict["one"] = 2 # {'one': 4} 这种方式也可以调用__setitem__

输出:

 

 c.python中Dcit实际也有子类实现:defaultdict

使用:

from collections import defaultdict # 这个是dict的子类
mydict = defaultdict(dict)
myvalue = mydict["bai"] # 如果不存在的话,返回{}

输出:

 

4.set和frozenset

a.两者是啥有啥特点?

set:集合(无序,不重复,可变)

frozenset:不可变集合(无序,不重复,不可变)

frozenset没有改变的方法 一旦初始化了 就不可变了。其中,不可变类型对可变类型的一个特点,不可变类型是可以作为dict的key的。
 
b.set常用操作
a=set('abcdee')
a.add('f')
print(a)
another_set=set('defgh')
#添加数据
#a.update(another_set)
#print(a)
#集合的差集
re_set=a.difference(another_set)
#减法实现于__ior__魔法函数
re_set2=a-another_set
#集合的交集&
re_set3=a&another_set
#集合的并集|
re_set4=a|another_set
print(re_set)
print(re_set2)
print(re_set3)
print(re_set4)
#也可以用if in判断(实现于__contains__魔法函数)
if 'a' in re_set:
    print('I am a set')

 

5.set和dict的原理

之前就提过,set的性能棒的。dict的查询性能远比起list要好。

并且list中随着list数据的增大,查找时间会增大,而dict不会。

这是为什么呢?

因为dict使用hash这种数据结构存储。set也是。

a.dict的散列表

特点:

- dict的key必须是可hash的,不可hash的是不能当成dict的key的,比如list
- python申请内存的时候,会初始化一个小的连续的空空间
- 由上一条可得这样 一定会存在浪费,这时候每次变动操作 会计算剩余空间,剩余空间小于1/3的时候,会重新生成空间并且将现在数据都拷贝过去(rehash)
- 数组比这种链表结构好的地方,就是可以直接根据偏移量来存取,而不用全部开始从头遍历。
(这种结构hash和重hash的策略用在很多地方,包括redis等)
 
b.存储结构了解了,那么数据的查找过程呢?

先计算a的散列值,查找表源是否为空,

因为a是不变的,所以如果表源为空,那么就会抛出key error。

如果表源不为空,也有可能是其他key,查看key是否是要查找的key。

如果是其他key,重新散列循环查找。

 

c.这种hash结构在ptthon中的特点

- 我们可以用__hash__这个魔法函数实现可hash对象

 - dict内存开销比较大,这是hash表的特点。

- 实际上python内部类和对象,都是dict。

- dict存储顺序和元素添加顺序有关。

- 插入数据后检查剩余空间引发的重hash,会影响原来的数据(比如地址)。

 

Guess you like

Origin www.cnblogs.com/besttr/p/11531222.html