python开发我爱编程

流畅的python

2018-02-14  本文已影响29人  宝宝家的隔壁老王

2、序列构成的数组

2.1、内置序列的类型

或者

2.2、列表推导和生成器
2.2.4、生成器表达式
2.3、元组
2.3.2、元组的拆包
2.3.3、嵌套元组拆包
2.3.4、具名元组
2.4、切片
2.4.1、为什么会忽略最后一个元素
2.4.2、对对象进行切片
2.4.4、
2.5、对序列使用 + 和 *

在拼接的过程中,两个被操作的序列都不会被修改,Python会新建一个包含同样数据类型数据的序列来作为拼接的结果。

坑:如果使用my_list=[[]] * 3 来初始化一个列表组成的列表,得到的列表包含的3个元素其实是3个引用,而且3个引用指向的都是同一个列表。

2.6、序列的增量赋值
2.7、list.sort
2.9、当列表不是首选时
2.10、Numpy, Scipy
2.9.4、双向队列和其他形式的队列
>>> from collections import deque

>>> dq = deque(range(10), maxlen=10)  # 可选参数,表示容纳的数量

>>> dq.rotate(2)  # 旋转操作

>>> dq.appendleft(-1)  # 尾部添加元素,会挤掉开始的元素

>>> dq.extend([11,12,13])  # 列表内容逐渐添加

3、字典和集合

3.1、泛映射型
3.2、字典推导
3.3、常见的映射方法
3.4.2、特殊方法 __missing__
3.5、字典的变种
>>> from collections import ChainMap
>>> m = ChainMap({1:1}, {'a':1}, {'a':2})
>>> m['a']
>>> 2
3.6、子类化UserDict
3.7、不可变映射类型
3.8、集合论
3.8.1、句法陷阱
>>> from dis import dis
>>> dis('{1}')
>>> dis('set([1])')
3.8.2、集合推导
3.9、dict和set的背后
3.9.3、dict的实现和其导致的结果
3.9.4、set的实现以及导致的后果

4、文本和字节序列

4.1、字符问题
4.5、处理文本文件
5、一等函数
5.2、高阶函数
5.3、匿名函数
5.4、可调用对象
5.6、函数内省
5.7、从定位参数到仅限关键字参数
5.8、函数对象有个__defaults__属性,值是一个元组,里面保存着定位参数和关键字参数的默认值。仅限关键字参数的默认值在__kwdefaults__属性中

6、使用一等函数实现设计模式

6.1、策略模式
6.1.4
6.2、命令模式

7、函数装饰器和闭包

7.1、装饰器
7.2、python何时执行装饰器
7.4、变量作用域规则
7.5、闭包
7.6、nonlocal声明
7.8、标准库中的装饰器

三个用于装饰方法的函数

7.8.1、使用functools.lru_cache
7.8.2、functools.signaledispatch装饰器
7.9、叠放装饰器
@d1
@d2
def f():
    print('f')

相当于f = d1(d2(f))

7.10、参数化装饰器
7.10.1、一个参数化的注册装饰器
7.10.2、参数化clock装饰器

8、对象引用,可变性和垃圾回收

8.1、变量不是盒子
8.2、标志,相等性和别名
8.2.1、在==和is之间选择
8.2.2、元组的相对不可变性
8.3、默认做浅复制
>>> l1 = [3,4,5]
>>> l2 - list(l1)
>>> l2 == l1
>>> True
>>> l2 is l1
>>> False
8.4、函数的参数作为引用时
8.4.1、不要使用可变类型作为参数的默认值

8.5、del和垃圾回收

8.6、弱引用

因为有引用,对象才会在内存中存在。当对象的引用数量归零后,垃圾回收程序会把对象销毁。

8.6.2、弱引用的局限
8.7、Python对不可变类型施加的把戏

9、符合Python风格的对象

9.1、对象表示形式
9.3、备选构造方法
9.4、classmethod与staticmethod
9.5、格式化显示
9.6、可散列的
9.8、使用slots属性节省空间

10、序列的修改,散列和切片

10.3、协议和鸭子类型
10.4.1、切片原理
10.5、动态存取属性

11、从协议到抽象基类

11.1、python文化中的接口和协议
11.5、定义抽象基类的子类
11.6、标准库中的抽象基类
11.6.2 抽象基类的数字塔

numbers包定义的数字塔,Number是位于最顶端的超类,随后是Complex子类,依次往下

11.9、python使用register的方式
在 collections.abc模块的源码中,使用
Sequence.register(tuple)
Sequence.register(str)
Sequence.register(range)
Sequence.register(memoryview)
注册为Sequence虚拟子类的

12、继承的优缺点

12.2、多重继承和方法解析顺序
def ping(self):
    A.ping(sef)
    print('post-ping:', self)

13、正确重载运算符

运算符重载的作用是让用户定义的对象使用中缀运算符,如+和|或一元运算符如-和~。

13.1、运算符重载基础
13.2、一元运算符

14、可迭代的对象,迭代器和生成器

14.2、可迭代的对象与迭代器的对比
14.10、python3.3新出现语法yield from
14.11、可迭代的规约函数
14.12、深入分析iter函数
iter函数有一个鲜为人知的用法,传入两个参数,使用常规的函数或任何可调用的对象创建迭代器。第一个参数必须是可调用的对象,用于不断调用(没有参数),产出各个值,第二个值是哨符,是标记值,当可调用的对象返回这个值时,触发迭代器跑出StopIteration异常,不产出哨符。
14.14、把生成器当成协程

15、上下文管理器和else块

with语句会设置一个临时的上下文,交给上下文管理器对象控制,并且负责清理上下文,更安全易于使用,除了自动关闭文件之外,with块还有跟多用途。
15.2、上下文管理器和with块
15.3、contextlib模块中的使用工具
15.4、使用@contextmanager

16、协程

16.1、生成器进化成协程
16.3、使用协程计算移动平均值
def ave():
    total, count, average = 0.0, 0, None
    while True:
        term = yield average
        total += term
        count += 1
        average = total/count
16.4、预激协程的装饰器
16.5、终止协程和异常处理

客户代码可以在生成器对象上调用两个方法,显示的把异常发给协程

python 3.3引入yield from结构的主要原因之一与把异常传入嵌套的协程有关。另一个原因是让协程更方便的返回值。
16.6、让协程返回值

捕获StopIteration异常,获取averager返回的值。yield from 结构会在内部自动捕获StopIteration异常。循环机制使用用户易于理解的方式处理异常。对于yield from结构来说,解释器不仅会捕获StopIteration异常,还会把value属性的值变成yield from表达式的值。

16.7、yield from
yield from x 表达式对x对象所做的第一件事是,调用iter(x),从中获取迭代器。因此x可以是任何可迭代的对象。
yield from结构的本职作用无法通过简单的可迭代对象说明,而要发散思维,使用嵌套的生成器

yield from的主要功能是打开双向通道,把最外层的调用方和最内层的子生成器连接起来,二者可以直接发送和产出值,还可以直接传入异常。

thread_ = threading.Thread()
thread_.start()  # 开始
thread_.join()  # 阻塞到结束

17、使用期物处理并发

17.1、示例
from concurrent import futures
with futures.ThreadPoolExecutor(10) as executor:
    res = executor.map(fun1, list_args)
return len(list(res))  # 从此处会阻塞
17.1.3、期物在哪
17.2、阻塞型I/O和GIL
17.3、使用concurrent.futures模块启动进程

18、使用asyncio包处理并发

适合asyncio的协程在定义体中必须使用yield from而不能使用yield,此外 asyncio 协程要由调用方驱动;或者把协程传给asyncio包中的某个函数如asyncio.async(...)
@asyncio.coroutine装饰器应该应用在协程上
18.1.1、asyncio.Future故意不阻塞
18.1.2、从期物,任务和协程中产生
asyncio包中有多个函数会自动把参数指定的协程包装在asyncio.Task对象中,例如BaseEventLoop.run_until_complete()
@asyncio.coroutine
def get_flag(cc):
    url = ''
    resp = yield from aiohttp.request('GET', url)
    image = yield from resp.read()
    return image
def get_flag(cc):
    url = ''
    resp = aiohttp.request('GET', url)
    image = resp.read()
    return image
使用asyncio包,我们编写的异步代码中包含由asyncio本身驱动的协程(即委派生成器),而生成器最终把职责委托给asyncio包或第三方库中的协程。这种处理方式相当于假期了管道,让asyncio时间循环驱动执行底层异步I/O操作的库函数

19、元编程

19.1、动态属性
19.1.3、使用__new__方法灵活的方式创建对象
19.2、使用特性验证属性
19.3、特性全解析

property构造方法的完整签名如下

property(fget=None, fset=None, fdel=None, doc=None)
19.3.1、特性会覆盖实例属性
19.3、特性的文档
class A:
    @property
    def bar(self):
        '''the bar attribute'''
        return self.__dict__['bar']
    @bar.setter
    def bar(self, value):
        self.__dict__['bar'] = value
19.4、定义一个特性工厂函数
class LineItem:
    weight = quantity('weight')
    price = quantity('price')
    
    def __init__(self, weight, price):
        self.weight = weight
        self.price = price
    def subtotal(self):
        return self.weight * self.price

def quantity(name):
    def name(instance):
        return instanch.__dict__[name]
    def name_set(instance, value):
        if value > 0:
            instance.__dict__[name] = value
        else:
            raise ValueError('value must be > 0')
19.5、处理属性删除操作
19.6、处理属性的重要属性和函数
19.6.1、
19.6.2、处理属性的内置函数
import dis
dis.dis(func)
19.6.3、处理属性的特殊方法

20、属性描述符

20.1、描述符示例
20.2、覆盖型与非覆盖型描述符对比
python 存取属性的方式特别不对等。实例读取属性时,通常返回的是实例中定义的属性,如果实例中没有指定的属性,那么会获取类属性。而为实例中的属性赋值时,通常会在实例中创建属性,不会影响类。

容器,迭代器,生成器
容器一定是可迭代的;
生成器一定是迭代器;
实现__iter__()和__next__()方法的是迭代器;
如果函数中出现了yield关键字,那么该函数就不再是普通函数,而是生成器函数。
上一篇下一篇

猜你喜欢

热点阅读