第03章 Python语言基础
2021-02-19 06:18
标签:分析 none 线程安全 开源 unit test test 多进程 web应用 prim Python是静态还是动态类型?是强类型还是弱类型? ◆动态强类型语言(不少人误以为是弱类型) ◆动态还是静态指的是编译期还是运行期确定类型 ◆强类型指的是不会发生隐式类型转换 为什么要用 Python? ◆胶水语言,轮子多,应用广泛 ◆语言灵活,生产力高 ◆性能问题、代码维护问题、 python2/3兼容问题 动态语言一时爽,代码重构火葬场。 当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。 ◆关注点在对象的行为,而不是类型(duck typing) ◆比如file, StringIO, socket 对象都支持read/write方法(file like object) ◆再比如定义了__iter__魔术方法的对象可以用for迭代 鸭子类型更关注接口而非类型 什么是 monkey patch?哪些地方用到了?自己如何实现? ◆所谓的 monkey patch就是运行时替换 ◆比如 gevent库需要修改内置的 socket from gevent import monkey;monkey.patch_socket() print(socket.socket) print("After monkey patch") from gevent import monkey monkey.patch_socket() import select print(select.select) # import time print(time.time()) # 1613097577.3560631 Introspection ◆运行时判断一个对象的类型的能力 ◆ Python-切皆对象,用type,id, isinstance 获取对象类型信息 ◆ Inspect 模块提供了更多获取对象信息的函数 print(isinstance(ll, list)) = 判断两个变量的值是不是相同 is 判断内存地址是否相同 is None None 本身是单例 List Comprehension ◆ 比如[i for i in range(10) if i%2 == 0] ◆ 一种快速生成 list/dict/set的方式。用来替代map/filter等 ◆ (i for i in range(10)if i%2 == 0) 返回生成器 The Zen of Python ◆ Tim Peters 编写的关于 Python编程的准则 ◆ import this ◆编程拿不准的时候可以参考 使用 pyenv安装 多版本 Python ◆ print成为函数 ◆ 编码问题。 Python3不再有 Unicode对象,默认str就是 unicode ◆ 除法变化。 Python3除号返回浮点数 ◆类型注解(type hint)。帮助IDE实现类型检查 ◆优化的 super0方便直接调用父类函数。 ◆高级解包操作。a,b,*rest= range(10) ◆类型注解(type hint)。帮助IDE实现类型检查 ◆优化的 super() 方便直接调用父类函数。 ◆高级解包操作。a,b,*rest= range(10) ◆ Keyword only arguments。限定关键字参数 ◆ Chained exceptions. Python3 重新抛出异常不会丟失栈信息 ◆ 一切返回迭代器 range,zip,map, dict values, etc. are all iterators ◆ yield from 链接子生成器 ◆ asyncio 内置库, async/await 原生协程支持异步编程 ◆ 新的内置库enum, mock, asyncio, ipaddress, concurrent.futures 等 ◆生成的pyc文件统一放到__pycache__ ◆一些内置库的修改。 urlib,selector 等 ◆性能优化等。。。 熟悉一些兼容2/3的工具 ◆ six 模块 ◆ 2to3等工具转换代码 ◆ __future__ Python函数常考题 常考点: 一个容易混淆的问题 传递值还是引用呢?都不是。唯一支持的参数传递是共享传参 Call by Object( Call by Object Reference or Call by Sharing Call by sharing(共享传参)。函数形参获得实参中各个引用的副本 s 创建一个新的对象 hehe 指向的同一个对象 一切是对象 对象引用的方式 实参和形参指向同一个对象 不可变对象看起来 像是拷贝了一份 实则不是 是创建了一份 创建一个新的对象,让形参指向新的 什么是 Python的异常? Python 使用异常处理错误(有些语言使用错误码) ◆ BaseException ◆ SystemExit/KeyboardInterrupt/GeneratorExit ◆ Exception 什么时候需要捕获处理异常呢?看 Python 内置异常的类型 ◆ 网络请求 (超时、连接错误等) ◆ 资源访问 (权限问题、资源不存在) ◆ 代码逻辑 (越界访问、 KeyError等) 如何自定义自己的异常?为什么需要定义自己的异常? ◆ 继承 Exception 实现自定义异常 (想想为什么不是 BaseException) ◆ 给异常加上一些附加信息 ◆ 处理一些业务相关的特定异常(raise MyException) CtrlC 也是异常 捕捉不到 GIL, Global Interpreter Lock ◆ Cpython解释器的内存管理并不是线程安全的 ◆ 保护多线程情况下对 Python 对象的访问 ◆ Cpython 使用简单的锁机制避免多个线程同时执行字节码 限制了程序的多核执行 ◆ 同一个时间只能有一个线程执行字节码 ◆ CPU 密集程序难以利用多核优势 ◆ IO 期间会释放GIL,对IO密集程序影响不大 区分CPU和IO密集程序 ◆ CPU密集可以使用多进程+进程池 ◆ IO密集使用多线程/协程 ◆ cython扩展 问题:请问这段代码输出? Python中什么操作才是原子的?一步到位执行完 ◆ 一个操作如果是一个字节码指令可以完成就是原子的 ◆ 原子的是可以保证线程安全的 ◆ 使用dis操作来分析字节码 原子操作 非原子操作不是线程安全的 使用各种 profile 工具(内置或第三方) ◆二八定律,大部分时间耗时在少量代码上 ◆内置的 profile/cprofile 等工具 ◆使用 pyflame(uber开源)的火焰图工具 Web应用一般语言不会成为瓶颈 ◆数据结构与算法优化 ◆数据库层:索引优化,慢查询消除,批量操作减少IO,NoSQL ◆网络IO:批量操作, pipeline操作减少IO ◆缓存:使用内存数据库 redis/memcached ◆异步:asyncIO, celery ◆并发:gevent/多线程 ◆生成器就是可以生成值的函数 ◆当一个函数里有了 yield 关键字就成了生成器 ◆生成器可以挂起执行并且保持当前执行的状态 Python3 之前没有原生协程,只有基于生成器的协程 ◆pep 342( Coroutines via Enhanced generators)增强生成器功能 ◆生成器可以通过 yield暂停执行和产出数据 ◆同时支持send() 向生成器发送数据和 throw()向生成器抛异常 Generator Based Coroutine示例 避免每次都要用send预激它 python2 yield 的协程 流畅的python Python3.5 引入 async/await 支持原生协程 (native coroutine) Unit Testing ◆针对程序模块进行正确性检验 ◆一个函数,一个类进行验证 ◆自底向上保证程序正确性 三无代码不可取(无文档、无注释、无单测) ◆保证代码逻辑的正确性(甚至有些采用测试驱动开发(TDD)) ◆单测影响设计,易测的代码往往是高内聚低耦合的 ◆回归测试,防止改一处整个服务不可用 单元测试相关库 ◆ nose/pytest 较为常用 ◆ mock 模块用来模拟替换网络请求等 ◆ coverage 统计测试覆盖率 深拷贝与浅拷贝的区别 ◆ 什么是深拷贝?什么是浅拷贝? ◆ Python中如何实现深拷贝? ◆ 思考:Python中如何正确初始化一个二维数组? 第03章 Python语言基础 标签:分析 none 线程安全 开源 unit test test 多进程 web应用 prim 原文地址:https://www.cnblogs.com/wenyule/p/14408004.htmlPython语言特性
Python作为后端语言优缺点
什么是鸭子类型
class Duck:
def quack(self):
print("gua gua")
class Person:
def quack(self):
print("我是人类")
def in_the_forest(duck):
duck.quack()
def game():
donald = Duck()
john = Person()
in_the_forest(donald)
in_the_forest(john)
print(type(donald))
print(type(john))
if __name__ == ‘__main__‘:
game()
什么是 monkey patch
import socket
print(socket.socket)
monkey.patch_select()
print("after monkey patch")
print(select.select)
# After monkey patch
#
#
# after monkey patch
#
def _time():
return 1234
time.time = _time
print(time.time()) # 1234什么是自省?
ll = [1, 2, 3]
d = dict(a=1)
print(type(ll))
print(type(d))
print(isinstance(d, dict))什么是列表和字典推导
知道 Python之禅吗
Python2/3差异常考题
Python3 改进
Python3 改进
Python3 新增
Python3 改进
Python2/3工具
Python 如何传递参数
Python 异常机制常考题
使用异常的常见场景
如何处理 Python 异常
try:
# func # 可能会抛出异常的代码
except (Exception1, Exception2) as e: # 可以捕获多个异常并处理
# 异常处理的代码
else:
# pass # 异常没有发生的时候代码逻辑
finally:
pass # 无论异常有没有发生都会执行的代码,一般处理资源的关闭和释放
如何自定义异常
class MyException(Exception):
pass
try:
raise MyException(‘my exception‘)
except MyException as e:
print(e)
Python性能分析与优化GIL常考题
什么是 Cpython GIL
GIL的影响
如何规避GIL影响
GIL的实现
import threading
n = [0]
def foo():
n[0] = n[0] + 1
n[0] = n[0] + 1
threads = []
for i in range(5000):
t = threading.Thread(target=foo)
threads.append(t)
for t in threads:
t.start()
print(n)
为什么有了GIL还要关注线程安全
import dis
def update_list(l):
l[0] = 1 # 原子操作,不用担心线程安全问题
dis.dis(update_list)
"""
5 0 LOAD_CONST 1 (1)
2 LOAD_FAST 0 (l)
4 LOAD_CONST 2 (0)
6 STORE_SUBSCR #单字节码操作,线程安全
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
"""
import dis
def update_list(l):
l[0] += 1
dis.dis(update_list)
"""
5 0 LOAD_FAST 0 (l)
2 LOAD_CONST 1 (0)
4 DUP_TOP_TWO
6 BINARY_SUBSCR
8 LOAD_CONST 2 (1)
10 INPLACE_ADD #需要多个字节码操作,有可能在线程执行过程中切到其他线程
12 ROT_THREE
14 STORE_SUBSCR
16 LOAD_CONST 0 (None)
18 RETURN_VALUE
"""
如何剖析程序性能
服务端性能优化措施
什么是生成器
Generator
def simple_gen():
yield ‘hello‘
yield ‘world‘
gen = simple_gen()
print(type(gen)) #
print(next(gen)) # hello
print(next(gen)) # world
基于生成器的协程
def coro():
hello = yield ‘hello‘ # yield 关键宇在右边作为表达式,可以被send值
yield hello
c = coro()
print(next(c)) # 输出 ‘hello‘,这里调用next 产出第一个值‘hello‘,之后函数暂停
print(c.send(‘world‘)) # 再次调用send发送值,此时he1lo变量值为‘ world‘,然后yie1d产出hell0变量的值‘world‘
# 之后协程结束,后续再send值会抛异常 StopIteration
#hello
#world
协程的注意点
协程装饰器
from functools import wraps
def coroutine(func): # 这样就不用每次都用 send(None)启动了
""" 装饰器:向前执行到第一个`yield` 表达式,预激 `func` """
@wraps(func)
def primer(*args, **kwargs):
gen = func(*args, **kwargs)
next(gen)
return gen
return primer
Python3 原生协程
import asyncio
import datetime
import random
async def display_date(num, loop):
end_time = loop.time() + 50.0
while True:
print(‘Loop: {} Time: {}‘.format(num, datetime.datetime.now()))
if (loop.time() + 1.0) >= end_time:
break
await asyncio.sleep(random.randint(0, 5))
loop = asyncio.get_event_loop()
asyncio.ensure_future(display_date(1, loop))
asyncio.ensure_future(display_date(2, loop))
loop.run_forever()
Python单元测试
什么是单元测试
为什么要写单元测试
单元测试相关的库
Python深拷贝与浅拷贝
下一篇:12Java泛型