Tôi đã phải đăng bài này lên một câu hỏi tương tự cho đến khi điểm danh tiếng của tôi tăng lên một chút (nhờ bất cứ ai làm tôi bực mình!).
Tất cả các giải pháp này đều bỏ qua một cách để làm cho việc này chạy nhanh hơn đáng kể, cụ thể là bằng cách sử dụng giao diện không có bộ đệm (thô), sử dụng phụ, và thực hiện bộ đệm của riêng bạn. (Điều này chỉ áp dụng trong Python 3. Trong Python 2, giao diện thô có thể được sử dụng theo mặc định, nhưng trong Python 3, bạn sẽ mặc định thành Unicode.)
Sử dụng một phiên bản sửa đổi của công cụ thời gian, tôi tin rằng đoạn mã sau nhanh hơn (và hơi nhiều pythonic) hơn bất kỳ giải pháp nào được cung cấp:
def rawcount(filename):
f = open(filename, 'rb')
lines = 0
buf_size = 1024 * 1024
read_f = f.raw.read
buf = read_f(buf_size)
while buf:
lines += buf.count(b'\n')
buf = read_f(buf_size)
return lines
Sử dụng một chức năng tạo riêng biệt, điều này sẽ chạy nhanh hơn:
def _make_gen(reader):
b = reader(1024 * 1024)
while b:
yield b
b = reader(1024*1024)
def rawgencount(filename):
f = open(filename, 'rb')
f_gen = _make_gen(f.raw.read)
return sum( buf.count(b'\n') for buf in f_gen )
Điều này có thể được thực hiện hoàn toàn với các biểu thức trình tạo nội tuyến bằng itertools, nhưng nó trông khá kỳ lạ:
from itertools import (takewhile,repeat)
def rawincount(filename):
f = open(filename, 'rb')
bufgen = takewhile(lambda x: x, (f.raw.read(1024*1024) for _ in repeat(None)))
return sum( buf.count(b'\n') for buf in bufgen )
Dưới đây là thời gian của tôi:
function average, s min, s ratio
rawincount 0.0043 0.0041 1.00
rawgencount 0.0044 0.0042 1.01
rawcount 0.0048 0.0045 1.09
bufcount 0.008 0.0068 1.64
wccount 0.01 0.0097 2.35
itercount 0.014 0.014 3.41
opcount 0.02 0.02 4.83
kylecount 0.021 0.021 5.05
simplecount 0.022 0.022 5.25
mapcount 0.037 0.031 7.46