ฉันต้องโพสต์คำถามนี้ด้วยคำถามที่คล้ายกันจนกระทั่งคะแนนชื่อเสียงของฉันเพิ่มขึ้นเล็กน้อย (ขอบคุณผู้ที่กระแทกฉัน!)
โซลูชันทั้งหมดเหล่านี้ไม่สนใจวิธีหนึ่งในการทำให้การดำเนินการนี้เร็วขึ้นอย่างมากนั่นคือโดยใช้อินเทอร์เฟซที่ไม่มีบัฟเฟอร์ (ดิบ) ใช้การทดสอบแบบไบต์และการบัฟเฟอร์ของคุณเอง (สิ่งนี้ใช้ได้เฉพาะใน Python 3 เท่านั้นใน Python 2 อินเทอร์เฟซแบบดิบอาจใช้หรือไม่ใช้เป็นค่าเริ่มต้น แต่ใน Python 3 คุณจะเริ่มต้นเป็น Unicode)
การใช้เครื่องมือกำหนดเวลาเวอร์ชันที่แก้ไขแล้วฉันเชื่อว่ารหัสต่อไปนี้เร็วกว่า (และ pythonic เล็กน้อย) มากกว่าโซลูชันที่เสนอ:
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
การใช้ฟังก์ชั่นเครื่องกำเนิดไฟฟ้าแยกต่างหากจะทำให้ smidge ทำงานได้เร็วขึ้น:
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 )
สามารถทำได้อย่างสมบูรณ์ด้วยนิพจน์กำเนิดในบรรทัดโดยใช้ itertools แต่มันก็ดูแปลก ๆ :
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 )
นี่คือการกำหนดเวลาของฉัน:
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