问题记录

关于切片和拷贝的深度

想用 matplotlib 画一个动态图,但是数据是实现读取好的。所以只能不断改变画图数据的大小来实现 plot 的动态过程。 想到两种方法,一个是新建一个 array,然后每一次迭代都 append 一个数据进去,然后 plot 这个 array,另一种方法 是每次对原始数据进行切片,后画图。

后来采用的是切片的方法,发现速度竟然比 append 要快很多,总觉得每一步一次的 append 应该不会比对那么多数据进行浅复制的切片慢啊。

因为数据是存储在 numpy 的 ndarray 中和 Python 内置的 list 可能有些不一样。list 在切片的时候实际上是进行浅拷贝的,而 ndarray 在切片时是返回一个 view(numpy 名词),共享核心数据,但其他的属性例如 shape 等都是不影响的。可能 ndarray 的核心数据都是 flatten 之后存储的吧。

总之,append 很慢,如果知道数组长度就预先分配好空间,如果不知道也尽量少做 append 或者 resize 的操作,用空间换时间是更优解吧。

input 和 stdin.readline

input() 读取一行并丢弃 回车

而 sys.stdin.readline() 读取一行但不会丢弃回车

输入流中都不再有 delim 字符

另外 stdin 中还有 read(size) readlines() 方法

readlinereadlines 方法都读取并保留行尾的 '\n'

int() 在接受 str 作为参数时,会自动去掉行尾的 '\n'

>>> int('123\n')
123

Python 读取文件的几个函数以及大文件读写

read() 函数一次性读取整个文件,如果是大文件通常反复调用 read(size) 比较保险,每次读取 size 个字节。

另外 readline 每次读取一行内容,而 readlines 一次性读取所有行并返回一个 list

读取大文件的一个封装

def read_in_chunks(filePath, chunk_size):
    file_object = open(filePath)
    while True:
        chunk_data = file_object.read(chunk_size)
        if not chunk_data:
            break
        yield chunk_data

if __name__ == "__main__":
    filePath = './path/filename'
    for chunk in read_in_chunks(filePath):
        pass

另外 也可以通过 iter 和 partial 更简单的实现这一功能

from functools import partial

def readanddraw():
    with open(filePath) as f:
        chunks = iter(partial(f.read, chunksize), '')
        for chunk in chunks:
            pass

iter() 函数有一个鲜为人知的特性就是,如果你给它传递一个可调用对象和一个 标记值,它会创建一个迭代器。这个迭代器会一直调用传入的可调用对象直到它返回标 记值为止,这时候迭代终止。

综上,对于大文件,要么 readline 要么 按固定大小读取文件。