数据类型&推导式&生成器&迭代器

一、元组和列表

1.元祖和列表的性能分析

  • 测试环境:ipython 中使用 timeit模块
  • 计算时间模块介绍:
# ipython环境下
In [1]: timeit list1=[1,2,3]
42.3 ns ± 1.2 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [2]: timeit tuple1=(1,2,3)
12.3 ns ± 0.0096 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)

# 总结:可以看到初始化列表一千万次是初始化一千万次元组时间的三倍多,所以在数据确认的情况下尽可能使用元组储存数据
import timeit  # python下用来性能分析


def func():
    for i in range(10):
        print(i)


# 函数等需要传函数名 
times = timeit.timeit(func, number=5)
print(times)
# 数据类型需要传字符串,number默认值一千万次
times=timeit.timeit("[1,2,3]")
print(times)

2.命名元组

正常元组的取值方式是通过下标,不够人性化,命名元组就实现可以像字典那样取值

  • 方式一(没事找事)
    # 方式一 ,先把先把下标赋值给key,然后就可以通过key取值了 太low
    tu=["小明",18,"男"]
    name=0
    age=1
    gender=2
    print(tu[name])
    print(tu[age])
    print(tu[gender])
  • 方式二 :collections 模块里的 namedtuple方法
    from collections import namedtuple

    # typename:类型名字 ,field_names:这个元组元素的名称,传一个列表
    info_tuple = namedtuple(typename="info_tuole", field_names=["name", "age", "gender"])
    # 单个元组
    tu = info_tuple("小明", 18, "男")
    print(tu)
    print(tu.age)

二、字典和集合的原理和应用

dict和set实现原理是一样的都是无序的,都是将实际的值放到list中,唯一不通的在于hash函数操作对象不同,对于dict,hash函数操作的是其key,而set是直接操作的它的元素,假设操作元素为“X”,其作为变量,放入hash函数,通过运算后取list的余数,作为list的下标存储起来,set就直接存放set本身元素,叫做hash set,而对于dict则是创建两个list,一个list存key,一个list存value,叫做hash map(map就是通过key找value的过程)

  • 定义集合set
    • 最大作用自动去重
    • 关系性测试数据:交集,并集,差集,对称差集
    # 定于空集合
    se = set()
    se.add(1)  # 单个添加
    se.update([1, 2, 3, 4, 2, 2])  # 添加多个
    se.remove(1)
    print(se)

    a=set([1,2,3,4,5,6])
    b=set([4,5,7,8,9])
    # 交集intersection
    print(a.intersection(b)) #>>>{5, 6}

    # 并集union
    print(a.union(b))  # >>>{1, 2, 3, 4, 5, 6, 7, 8, 9}

    # 差集:在a中不在b中的
    print(a.difference(b))  # >>>{1, 2, 3, 4}

    # 对称差集:反向交集
    print(a.symmetric_difference(b))  # >>>{1, 2, 3, 4, 7, 8, 9}

    # 超集:判断a是不是完全包含b  a>=b
    print(a.issuperset(b))

    # 子集:判断a是不是b的子集 a<=b
    print(a.issubset(b))
  • 字典

  • 性能分析
    • 从时间上(快-慢):集合、字典、元组、列表
    • 从内存上(少-多):元组、列表、集合、字典

三、推导式

  • 列表推导式
    # 如生成0-100的单数的平方列表
    list1 = [i*i for i in range(1, 101) if i % 2 == 1]
    print(list1)
  • 字典推导式
    cook_str = 'BIDUPSID=D0727533D7147B7;PSTM=1530348042;BAIDUID=B1005C9BC2EB28;sugstore=0'

    dict_str = {i.split("=")[0]: i.split("=")[1] for i in cook_str.split(";")}

四、生成器

  • 生成器表达式
    # 生成器表达式 内部实现了生成器协议-有__next__方法
    gen = (i for i in range(20))
    print(gen)
    print(dir(gen))
    # 通过next()方法生成一个取一个,取玩在取报错StopIteration
    print(next(gen))
    print(next(gen))
    print(next(gen))
    # 可以通过for 循环取值
    for i in gen:
        print(i)
  • 函数生成器
    • send方法
    • close方法
    • throw方法
    def gen_fun():
        for i in range(1,10):
            send_value = yield i
            print(send_value)

    # 赋值生成器对象
    res = gen_fun()
    print(res)
    # 执行到yield 返回1
    print(next(res))
    # 继续执行 给send_value赋值 因为不没有传 所以是None 执行打印None 在继续执行循环到yield,返回2
    print(next(res))
    # 继续执行 给send_value赋值 send的值100 打印100 执行打印100 在继续执行循环到yield,返回3
    # send方法在去过一次值后,程序执行到yield后菜能使用
    print(res.send(100)) 
    #继续执行 给send_value赋值 因为不没有传 所以是None 执行打印None 在继续执行循环到yield,返回2
    print(next(res))


    res_1=gen_fun()
    print(next(res_1))
    res_1.close()  # close 方法关闭生成器
    print(next(res_1))  # >>>StopIteration 报错


    res_2=gen_fun()
    # 让生成器抛错机制 第一个参数:异常类型 ;第二个参数:异常信息
    res_2.throw(ValueError,"value异常")  # >>>ValueError: value异常

五、迭代器

  • 可迭代对象是序列不是迭代器,可被for循环遍历取值,内部有__iter__()方法,没有__next__()方法
  • 可迭代对象可以通过iter方法实现可迭代协议,将可迭代对象转换成迭代器,内部有__next__()
  • 生成器是一种特殊的迭代器
  • 生成器相对迭代器多了几种方法(__del__,__qualname__,'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw')
   list_1=[1,2,3,4,5]
   iterator=iter(list_1)
   print(iterator)
   print(next(iterator))
   print(next(iterator))

猜你喜欢

转载自www.cnblogs.com/jiangmingbai/p/10903609.html