大一python考试知识点_Python基础知识点整理

参考资料

[1]. 廖雪峰

内容整理

函数

函数返回: 函数执行时遇到return即执行完毕, 返回结果; 没有return, 执行完毕返回None; return None可以简写为return.

内建函数: 高效快速, e.g. input(), ord(), pow(), isinstance(), iter()

局部变量: 比全局变量快, 尽量避免global; 但下文有提到全局字典保存不同线程专属对象的技巧

默认参数: 必须指向不变对象:函数在定义时, 默认参数值就会被计算出来

Python解释器: 只检查参数个数, 不检查参数类型. 但它会检查自己的内置函数参数格式和类型, 这不公平...对于自己写的函数, 可以用内置函数isinstance实现参数类型检查

1 if notisinstance(x, (int)):2 raise TypeError('not int type')

多返回值: return x, y, 当然本质是省略了括号的tuple

多重赋值: x,y = y,x 要比三条语句执行快

字符串连接: 和Java语法一样, 使用join()要比"+"高效, "+"会创建一个新的字符串并复制内容

延迟加载: ipmort在需要时再导入

无限循环: while 1比while True高效, 因为while 1是单步运算

列表生成式(list comprehension): 取代for和while更高效, 因为Python解释器能够在循环中发现它是一个可以预测的模式而被优化, 同时list更具可读性. 和Java一样, 可以在循环中节省一个额外的计数变量. e.g. evens = [i for i in range(10) if i%2 == 0] 要比 while i<10: if i%2 == 0: evens.append(i) i+=1 易读高效

生成器(generator): 里提到, 生成器保存的是算法, 每次调用next()时才会计算出下一个值, 返回后保存这次计算的位置. 里也给出了逐个字节发送视频流的例子: chunk=(1000*i for i in xrange(1000)), chunk.next(), chunk.next(). 从两个例子中可以看出生成器的共性: 是一个表达式, 再调用的时候才执行一次, 再次调用时执行第二次...而构造生成器, 要么是一个xrange表达式, 要么是在函数里合适的位置加入yield, 保存当前状态后返回本次计算结果

查找效率: dict和set的查找很快, 因为是哈希表实现. list的实现是数组, 所以在list前插入效率不高, 因为list的后续下标不得不全部改变. 类比到Java里的集合框架: ArrayList数组线性表不适合在中间插入, 因为要改变后续元素下标; Java的Set和Python的set一样都是元素不重复的, 而且由Hash实现. Java的集合框架太强大太繁杂, Python则简化了很多, 记住dict, set, list, tuple目前就够用了

装饰器: 目前只掌握了简单修饰, 加参数修饰的用法

进程和线程的基础知识

CPU执行代码是顺序执行, 单核CPU通过让任务交替执行, "模拟"除了多任务并发执行. 真正的多任务并发, 是在多核CPU上, 每个CPU负责执行一个任务. 但实际任务数量远多于CPU核心数量, 所以最终还是操作系统把多任务轮流调度到不同的核心上执行.

进程/线程和物理内存(寄存器)/CPU的关联: 函数调用, 会在栈中分配一块空间, 存放局部变量和参数, 调用结束, 栈空间被释放. 每个线程都有独立的栈, 寄存器. 同一进程里的所有线程共享文件, 代码和数据.

进程独立性: 以CPU中的程序计数器PC为例, 物理的PC只有一个, 但是每个进程有独立的逻辑PC, 保存了程序运行中的值, 但CPU轮到该进程时, 就将逻辑PC值复制到物理PC.

Python跨平台支持多进程

Unix/Linux平台Python支持fork(): 父进程复制出一个子进程

Windows平台Python支持Process(target,args): "模拟出fork()的效果", 即父进程所有Python对象pickle后传递给子进程

Python进程间通信的数据交换方式

multiprocessing模块提供的Queue, Pipes

Python多线程基础知识

标准库提供了两个模块: thread和threading(推荐).

任务进程都默认启动一个叫做MainThread的主线程, 主线程可以启动新的子线程.

多线程的变量锁: 高级语言的一条语句在CPU执行时是若干条语句, 计算中的结果会存入临时变量中, 每个线程都有自己的临时变量.

获取锁后一定要释放, 否则等待锁的线程会一直阻塞下去, 成为死线程. Python中可以通过try...finally确保释放.

锁的坏处: (1) 加锁的代码只能以单线程模式执行, 阻止了多线程并发, 降低效率; (2) 可能造成死锁.

Python的GIL锁导致多线程不能充分利用多核CPU

Python的解释器有一个GIL(Global Interpreter Lock)锁, 任何线程执行前, 先获得GIL锁, 每执行100行代码, 解释器会自动释放GIL锁, 让别的线程有机会执行. 所以即使100个线程跑在100核CPU上, 也只能用到1个核.

GIL是Python解释器设计的历史遗留问题, 使得Python不能有效利用多核, 但可以通过多进程实现.

多个Python进程有各自独立的GIL锁, 互不影响.

GIL: 只是CPython解释器存在. "GIL会序列化你的所有线程". 可以使用线程来管理多个派生进程, 使这些进程独立运行于Python代码之外.

多线程下选择加锁的全局变量or不得不传递下去的局部变量?

加锁和传递局部变量都是老方法了, 只是局部变量传递起来很麻烦. 如果遇到每个线程一个专属对象, 不能使用全局变量的情况, 作者就想到用一个全局dict, 但是通过线程自身作为key获得保存的对应的对象, 例如:

1 #-*-coding:utf-8 -*-

2 importtime, threading3

4 global_dict ={}5

6 classStudent(object):7

8 def __init__(self, name):9 self.name =name10

11 defreturn_name(self):12 returnself.name13

14

15 defdo_task_1():16 std = Student('Elsa')17 global_dict[threading.currentThread()] =std18 std =global_dict[threading.current_thread()]19 print 'thread %s, do_task_1() std.name = %s\n' %(threading.currentThread().name, std.return_name())20

21 defdo_task_2():22 std = Student('Anna')23 global_dict[threading.currentThread()] =std24 std =global_dict[threading.current_thread()]25 print 'thread %s, do_task_2() std.name = %s\n' %(threading.currentThread().name, std.return_name())26

27

28 if __name__ == '__main__':29 print 'thread %s is running...' %threading.currentThread().name30 t1 = threading.Thread(target=do_task_1, name='t1')31 t2 = threading.Thread(target=do_task_2, name='t2')32 t1.start()33 t2.start()34 t1.join()35 t2.join()36 print 'thread %s ended.' % threading.currentThread().name

global_dict ={}作为一个全局变量, 保存了线程和它的专属对象. 运行结果:

D:\WorkspaceVSCode>python multiprocess.py

thread MainThreadisrunning...

thread t1, do_task_1() std.name=Elsa

thread t2, do_task_2() std.name=Anna

thread MainThread ended.

然后Python又简化了对每个线程专属对象的存储和访问, 也就是封装了上面的global_dict = {}. 可以理解成, local_school = threading.local()是一个全局变量, 但它里面保存的是各个线程的局部变量, 还不用管理线程锁了, 感觉很方便的样子.

多线程时使用ThreadLocal用全局变量保存线程的局部变量

常用于为每个线程绑定一个数据库连接, HTTP请求, 用户身份信息等.

进程, 线程和计算密集, IO密集型任务

多进程更稳定, 系统的子进程互相内存独立, 子进程崩溃不会影响其它进程(主进程除外)

多线程更高效, 但由于所有线程共享进程的内存, 一个崩溃会引发系统强制结束整个进程

计算密集型任务,如视频高清解码, 主要开销在CPU计算, 任务数=核心数最好

IO密集型任务, 如网络, 磁盘IO等, CPU消耗很少, 大部分时间都是在等待IO操作完成, 任务越多, CPU效率越高(有限度)

CPU和IO操作间巨大的速度差异催生了异步IO

既然一个任务在执行时大部分时间都是CPU等待IO, 单进程单线程并不能充分的利用CPU资源, 在CPU等待IO的时候, 不放用空闲时间去执行CPU计算任务. "现代操作系统对IO操作已经做出了巨大改进, 最大的特点就是支持异步IO. 如果充分利用操作系统提供的异步IO支持, 就可以用单进程单线程模型来执行多任务." (Android里的AsyncTask就是一种异步, 但是它本质是另外起了一个小线程, 所以异步就是多线程?)

分布式多进程, 还能够通过网络共享任务队列

Python的multiprocessing模块, 支持多进程, 还支持多进程分布到多台设备

原理就是将多进程共享的Queue通过网络暴露出去, 其它机器就可以访问Queue了(就像remoterobotserver通过网络暴露出robot的库一样)

性能调优工具

python -m cProfile mypython.py

Native+包装器

Python程序可以直接加载已变成的二进制库(.dll或.so)文件, 不用编写C/C++代码(直接源码+NDK)或构建依赖(Gradle中添加.so库构建依赖)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值