函数 - 以下代码分别输出什么?Python如何传参?
# 代码1 def flist(l): l.append(0) print(l) l = [] flist(l) flist(l)
# 代码2 def fstr(s): s += 'a' print(s) s = 'hehe' flist(s) flist(s)
- Python唯一支持的参数传递是共享传参,函数形参获得实参中各个引用的副本。
- Python可变/不可变: 不可变对象 -> bool/int/float/tuple/str/frozenset
可变对象 -> list/dict/set
# 测试例子1 def clear_list(l): l = [] ll = [1,2,3] clear_list(ll) print(ll) # [1,2,3]
默认参数只计算一次。
# 测试例子2 def flist(l=[1]): l.append(1) print(l) flist() flist() # [1, 1] # [1, 1, 1]
函数 - Python *args ** kwargs 都是什么?
- 用来处理可变参数
- args 被打包成 tuple
- kwargs 被打包成 dict
Python异常机制 - 什么是Python异常?
Python使用异常处理错误(有些语言使用错误码)
- BaseException
- SystemExit/KeyboardInterrupt/GeneratorExit
- Exception
Python异常机制 - 什么时候需要捕获异常
- 网络请求(超时、连接错误等)
- 资源访问(权限问题,资源不存在)
- 代码逻辑(越界访问,keyerror)
Python异常机制 - 如何处理异常?
try: # fun - 可能会抛出异常的代码 except (Exception1, Exception2) as e: # 可以捕获多个异常并处理 # 异常处理代码 else: # pass 异常没有发生时候的代码逻辑 finally: # pass 无论异常有没有发生都会执行的代码,一般处理资源的关闭和释放
Python异常机制 - 如何自定义异常?
- 继承Exception实现自定义异常
- 给异常加上一些附加信息
- 处理一些业务相关的特定异常(raise MyException)
GIL-什么是CPython GIL?
- Cpython 解释器的内存管理并不是线程安全
- 保护多线程情况下对Python对象进行访问
- Cpython 使用简单的所机制避免多个线程同时执行字节码
GIL影响是?
- GIL限制了程序的多核执行
- 同一时间只能有一个线程执行字节码
- CPU密集程序难以利用多核优势
- IO期间会释放GIL,对IO密集程序影响不大
如何规避GIL影响?
- CPU密集可以使用多进程+进程池
- IO密集使用多线程/协程
- cython扩展
如何剖析程序性能?
- 二八定律,大部分时间耗时在少量代码上
- 内置的profile/cprofile等工具
- 使用pyflame的火焰图工具
什么是生成器
- 生成器就是可以生成值得函数
- 当一个函数里有了yield关键字就成了生成器
- 生成器可以挂起执行并且保持当前执行的状态
服务器端优化措施
- 数据结构与算法优化
- 数据库层:索引优化,慢查询消除,批量操作减少IO,Nosql
- 网络IO:批量操作,pipline操作减少IO
- 缓存:使用内存数据库 redis
- 异步:asyncio,celery
- 并发:gevent、多线程
为什么写单元测试?
- 避免三无代码(无文档,无注释,无单测)
- 保证代码逻辑的正确性
- 单测影响设计,易测代码往往是高内聚低耦合的
- 回归测试,防止改一处整个服务不可用
单元测试库有哪些?
- nose/pytest较为常用
- moke模块用来模拟替换网络请求
- coverage统计测试覆盖率