第四课 python进阶深入python的set和dict

第四课 python进阶深入python的set和dict

tags:

  • Python
  • 慕课网

categories:

  • set
  • dict

第一节 dict的abc继承关系

  1. dict就属于Lib_collections_abc.py中的mapping类型。
  2. MutableMapping是一个可修改的mapping, 和之前的序列类型一样继承Sized, Iterable, Container。
from collections.abc import Mapping, MutableMapping

a = {}
print(isinstance(a, MutableMapping))

第二节 dict的常用方法

a = {
     "bobby1": {"company": "imooc"},
     "bobby2": {"company": "imooc2"}
     }

# a.clear()
# pass

# copy, 返回浅拷贝
new_dict = a.copy()
new_dict["bobby1"]["company"] = "imooc3"

# 修改new_dict 发现a的内容也变了
print(a)
print(new_dict)

# 深copy 完全复制出一个对象此对象和之前对象地址不同
import copy
new_dict1 = copy.deepcopy(a)
new_dict1["bobby1"]["company"] = "imooc"
print(a)
print(new_dict1)

# formkeys
new_list = ["bobby1", "bobby2"]
new_dict3 = dict.fromkeys(new_list, {"company": "imooc"}) # 默认值{"company": "imooc"}
print(new_dict3)

# 用get防止key error错误 如果取不到返回""
print(new_dict3.get("bobby1", ""))

# setdefault 如果找不到就给它设置默认,返回设置的值
# setdefault 如果找到了不用设置,返回找到的值 性能高一些
default_value = new_dict3.setdefault("bobby1", "imooc")
print(default_value)
print(new_dict3)

# update可以合并字典
new_dict.update({"bobby": "imooc"})
print(new_dict)
# 键值对的方式
new_dict.update(bobby="imooc", bobby4="imooc")
print(new_dict)
# list里面放元组方式
new_dict.update([("bobby5", "imooc")])
print(new_dict)
# tuple中放tuple也可以
new_dict.update((("bobby6","imooc"),))
print(new_dict)

第三节 dict的子类

# 不建议继承list和dict
class Mydict(dict):
    def __setitem__(self, key, value):
        super().__setitem__(key, value*2)


# 第一个方法不会生效 第二个方法生效 如果直接继承dict可能有些方法不能使用
my_dict = Mydict(one=1)
my_dict["one"] = 1
print(my_dict)


# 如果要继承dict 继承这个就行了
from collections import UserDict


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


my_dict = Mydict(one=1)
# my_dict["one"] = 1
print(my_dict)


# 这个Lib\collections\__init__.py里面有一个__missing__魔法方法
# defaultdict如果找不到key 就会调用__missing__魔法方法
from collections import defaultdict

my_dict = defaultdict(dict)
my_value = my_dict["bobby"]
print(my_dict)

第四节 set和frontset

# set 集合 fronzenset (不可变集合) 无序, 不重复
# s = set('abcdee') # 自动去重
# s = set(['a','b','c','d','e']) # 无序
s = {'a', 'b', 'c'}
s.add('d')
print(type(s))
# 不可变集合frozenset frozenset可以作为dict的key
s1 = frozenset("abcdeee")
print(s)
print(s1)

# 向set添加数据
another_set = set("cef")
# 合并set
s.update(another_set)
# 差集
re_set = s.difference(another_set)
# re_set = s - another_set
# 交集
# re_set = s & another_set
# 并集
# re_set = s | another_set
# print(re_set)

# set和dict性能很高 背后实现原理是哈希
# | & -  #集合运算
# print(re_set)
# 判断是否是子集合
# print (s.issubset(re_set))
if "c" in re_set:
    print ("i am in set")

第五节 dict和set的实现原理

  1. dict的key或者set的值都必须是可以hash的
    • 不可变对象 都是可hash的, str, fronzenset, tuple,自己实现的类\ __hash__
  2. dict的内存花销大,但是查询速度快, 自定义的对象 或者python内部的对象都是用dict包装的
  3. dict的存储顺序和元素添加顺序有关
  4. 添加数据有可能改变已有数据的顺序
  5. dict和set查找性能对比
    • dict查找的性能远远超过list
    • 在list中随着list数据的增大 查找时间会增大
    • 在dict中查找元素不会随着dict的增大而增大
      在这里插入图片描述
      在这里插入图片描述
from random import randint


def load_list_data(total_nums, target_nums):
    """
        从文件中读取数据,以list的方式返回
        :param total_nums: 读取的数量
        :param target_nums: 需要查询的数据的数量
    """
    all_data = []
    target_data = []
    file_name = "D:/fbobject_idnew.txt"
    with open(file_name, encoding="utf8", mode="r") as f_open:
        for count, line in enumerate(f_open):
            if count < total_nums:
                all_data.append(line)
            else:
                break

    for x in range(target_nums):
        random_index = randint(0, total_nums)
        if all_data[random_index] not in target_data:
            target_data.append(all_data[random_index])
            if len(target_data) == target_nums:
                break

    return all_data, target_data


def load_dict_data(total_nums, target_nums):
    """
        从文件中读取数据,以dict的方式返回
        :param total_nums: 读取的数量
        :param target_nums: 需要查询的数据的数量
    """
    all_data = {}
    target_data = []
    file_name = "D:/fbobject_idnew.txt"
    with open(file_name, encoding="utf8", mode="r") as f_open:
        for count, line in enumerate(f_open):
            if count < total_nums:
                all_data[line] = 0
            else:
                break
    all_data_list = list(all_data)
    for x in range(target_nums):
        random_index = randint(0, total_nums-1)
        if all_data_list[random_index] not in target_data:
            target_data.append(all_data_list[random_index])
            if len(target_data) == target_nums:
                break

    return all_data, target_data


def find_test(all_data, target_data):
    # 测试运行时间
    test_times = 100
    total_times = 0
    import time
    for i in range(test_times):
        find = 0
        start_time = time.time()
        for data in target_data:
            if data in all_data:
                find += 1
        last_time = time.time() - start_time
        total_times += last_time
    return total_times/test_times


if __name__ == "__main__":
    # all_data, target_data = load_list_data(10000, 1000)
    # all_data, target_data = load_list_data(100000, 1000)
    # all_data, target_data = load_list_data(1000000, 1000)


    # all_data, target_data = load_dict_data(10000, 1000)
    # all_data, target_data = load_dict_data(100000, 1000)
    # all_data, target_data = load_dict_data(1000000, 1000)
    all_data, target_data = load_dict_data(2000000, 1000)
    last_time = find_test(all_data, target_data)
    print(last_time)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值