工程结构化
    时间层面,结构化意味着通过编写简洁的代码,并且正如文件系统中文件和目录的组织一样,代码应该逻辑和依赖清晰,在一个健康的开发周期中,代码风格,api设计和自动化是非常关键的,同样对于工程架构,仓库的结构也是关键的一部分。
    当一个潜在用户浏览你的git的时候,应该让他们看到
    工程名字
    工程描述
    一系列的文件
    结构格式:
    1,readme 对项目整体的介绍,同时也是一份使用手册,需要市场维护更新,通常为rst,或者md格式
    2,LICENSE 简述项目的许可说明和授权
    3,setup.py 通过setup吧核心代码打包发布
    4,sample,存放项目的核心代码
    5,requeirements.txt 存放该项目所有依赖的第三方库
    6,docs 包的参考文档
    7,tests 所有的代码测试都存于该目录下
    8,makefile 用于项目的命令管理(开源项目广泛使用)
    根据项目需求添加其他的文件和目录
    元祖和列表
    1,元祖和列表的性能分析
    计算创建元祖的时间和列表的时间
    在此可以使用python的第三方库 ipython
    timeit.timeit
    终端输入ipython可进入交互式变成
    通过timeit方法,执行命令并返回执行时间
    通过该方法可对比初始化元祖和列表,在性能上锁耗费的时间
    初始化列表时,一开始会定义一个容量,随着数量的增多会再次分配空间扩容
    初始化元祖时,容量会直接定死,所以元祖比列表所占用性能更少
    那么什么时候选用元祖,什么时候选用列表,
    假若一个变量集在定义之后会发生扩容,变动,则采用列表
    假若变量集定义之后不发生变动,则使用元祖
    2,命名元祖,
    常规元祖,在不知道内容数据的情况下想去取值只能通过下标会相当的麻烦,
    引入一个新的概念,命名元祖,可以通过对象属性的形式精准的从元祖中取到想要的数据
    涉及第三方库,from collections import namedtuple (命名元祖包

    1. stu_info = namedtuple('类型名字',['name','age','gender'])
    2. 参数1,参数2,列表,返回为一个对象
    3. stu_info = namedtuple('类型名字',['name','age','gender'])
    4. # param1 类型名字 param2 列表 返回为一个对象
    5. tu = stu_info("adi","18","man")
    6. print(tu.name)
    7. print(type(tu))
    8. print(type(stu_info))

    3,字典和集合
    空字典和空集合的定义方式
    set=set(),dict={}
    集合的最长用方法是去重,通过list转集合再转回list,内部数据犹豫set的特性已经完成去重。
    集合
    集合添加数据,
    set.add()一次只能添加一个元素,结合可变,可交集并集补集操作,但是常用在科学计算中。
    set.update({集合}) 将一个集合更新到另一个集合中,等同于列表中的extend方法
    set.copy() 复制方法 (TODO 查漏补缺
    字典和集合原理以及应用
    dict和set实现原理是一样的,都是将实际的值放在list中,唯一不同的点在于hash函数操作的对象。
    对于set
    hash函数操作的是dict的key,而set是直接操作它的元素,假设操作内容为X,其作为因变量放入hash函数,然后通过运算后取list的余数,转化为一个list的下标,此下标位置与对于set而言用来放其本身。
    对于dict
    而对于dict则是创建了两个list,一个list该下标放此key,另一个list中该下标放对应的value,
    其中把实现set的方式叫做hashset,实现dict的方式叫做hash map/table 。
    map值得就是通过key来寻找value的过程。dict 存的时候,一个列表存key,一个列表存value
    数值类型区分
    序列 字符串,列表,元祖
    散列 字典,集合,特征为内部元素是无序的
    注: py3.7之后,字典变为有序的,按照赋值的先后排序
    可变和不可变元素 其本质是可hash与,不可hash
    可变类型数据不可进行hash操作,不可变类型可以进进行hash操作
    集合有一个特殊的功能,如果有一个元素不知其是否为可变,就放到集合里面,集合里面只能存放可hash的不可变对象。
    可变 列表,字典,集合

    不可变 数字,字符串,元祖
    性能上的分析
    时间上 集合,字典,元祖,列表
    占用内存上 **字典,集合,列表,元祖

    推导式 重点掌握
    1,列表推导式
    案例1,要生成一个url列表 内涵数据[page1,page2,。。。]至100,传统for循环写法费事费力,推导式写法可以看成是for循环的简写
    url =[ F”page{i}” for i in range(1,100)]
    一行带么即可生成一个上面需求要求的列表
    2,字典推导式

    1. dic1 = {F'key{i}':F'value{i}' for i in range(10)}
    2. {'key0': 'value0', 'key1': 'value1', 'key2'...} 生成结构如这样的字典

    3,元祖推导式

    1. tu= (i for i in range(10)) 但是元祖推导式产生的并不是一个元祖,而是一个生成器对象、

    生成器表达式,是一个生成器。
    什么是生成器?
    内部保留生成的规则,调用一次方法生成一个值,像筷子盒的原理,通过这样节约内存
    将上面的生成器对象转换为list格式的话可以一次性取到所有生成器内在规则产生的数据。
    生成器可以通过next(生成器对象)方法来生成数据
    自定义生成器 yield关键字,通过yield 自定义生成器

    1. def gen_func():
    2. yield 100
    3. print("我是一个生成器")
    4. yield 1010
    5. yield 2020
    6. res = gen_func()
    7. print(next(res)) # 得到的是一个生成器对象
    8. print(next(res)) # 得到的是一个生成器对象

    什么是迭代器?
    创建一个迭代器对象,要实现迭代器的协议
    迭代协议?
    一种是包含iter()方法的,另一种是包含getitem()方法的
    比如str对象就没有iter方法,但是一样可迭代,
    即,实现了迭代器协议的对象为可迭代对象(实现方式,对象内部定义了一个iter方法)
    可迭代对象实现了next方法,方法返回了某个数值,该方法要求在值取完的时候,抛出StopIteration的错误信息

    迭代器与可迭代对象之间的转化
    比如将一个列表转化成一个迭代器 ,使用iter(可迭代对象)方法来进行转换,返回一个迭代器对象。
    迭代器与可迭代对象之间的区别
    迭代器内部实现了iternext方法,可迭代对象内部值实现了iter方法

    什么是生成器?
    生成器是迭代器的一种,除了iter,next,还实现了一些其他的方法
    send(),close(),throw()方法
    使用send方法可以与生成器进行交互

    1. def gen():
    2. for i in range(1,5):
    3. se = yield i
    4. print(se)
    5. g = gen()
    6. print(next(g))
    7. print(g.send(100)) # send可以将值发送进生成器

    生成器方法补充
    send()方法与生成器交互
    send方法一定要在next()执行一次之后才可使用,不然会报错
    作用是获取到上一次next产生的值并赋值为send进入的值
    close()方法
    关闭生成器,在关闭之后生成器不在具有生成器的next()方法,
    关闭之后再次调用next就会抛出异常
    throw()方法
    抛出异常的方法,g.throw(Exception,”method is not allow to call”)为使用格式