Python可变/不可变对象
可变对象:list / set / dict
不可变对象:bool / int / float / tuple / str / frozenset
eg:下面的代码会输出什么结果
def clear_list(l):
l = []
ll = [1,2,3]
clear_list(ll)
print(ll)
结果:[1, 2, 3]
Python可变参数作为默认参数:默认参数只计算一次
def flist(l=[1]):
l.append(l)
print(l)
fl()
fl()
结果:[1, 1]
[1, 1, 1]
什么是Python的异常?
Python使用异常处理错误。
- BaseExcepton
- SystemExit / KeyboardInterrupt / GeneratorExit
- Exception
使用异常的场景:什么时候需要捕获处理异常呢?看Python内置异常的类型
- 网络请求(超时、连接错误等)
- 资源访问(权限问题、资源不存在)
- 代码逻辑(越界访问、KeyError等)
如何处理异常?
try:
# func # 可能会抛出异常的代码
except (Exception1, Exception2) as e: # 可以捕获多个异常并处理
# 异常处理代码
else:
# pass # 异常没有发生的时候代码逻辑
finally:
pass # 无论异常有没有发生都会执行的代码,一般处理资源的关闭和释放
如何自定义异常?
继承Exception实现自定义异常。给异常加上一
些附加信息。处理一些业务相关的特定异常(raise MyException)
class MyException(Exception):
pass
try:
raise MyException('my exception')
except MyException as e:
print(e)
什么是Cpython GIL?
GIL,Global Interpreter Lock
Cpython解释器的内存管理并不是线程安全的,如果多线程会出现问题,在保护多线程情况下对Python对象的访问,Cpython使用简单的锁机制避免多个线程同时执行字节码
GIL的影响
限制了程序的多核执行:
- 同一个时间只能有一个线程执行字节码
- CPU密集程序难以利用多核优势
- IO期间会释放GIL,对IO密集程序影响不大
如何规避GIL影响
区分CPU和IO密集程序:
CPU密集可以使用多进程+进程池
IO密集可以使用多线程/ 协程
cython扩展
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)
结果:[10000] / [9998]