Пожалуйста, не пишите этот код:
while condition is False:
Булевы условия логические для вслух крика, так что они могут быть проверены (или отрицаны и проверены) напрямую:
while not condition:
Ваш второй цикл while не записан как «тогда как условие истинно:», мне любопытно, почему вы почувствовали необходимость проверить «ложно» в первом.
Вытащив модуль dis, я подумал, что расскажу об этом немного дальше. По моему опыту pyparsing, вызовы функций снижают общую производительность, поэтому было бы неплохо избегать вызовов функций, если это возможно. Вот ваш оригинальный тест:
>>> test = lambda t : t.startswith('customernum') is False
>>> dis.dis(test)
1 0 LOAD_FAST 0 (t)
3 LOAD_ATTR 0 (startswith)
6 LOAD_CONST 0 ('customernum')
9 CALL_FUNCTION 1
12 LOAD_GLOBAL 1 (False)
15 COMPARE_OP 8 (is)
18 RETURN_VALUE
Здесь происходят две дорогие вещи, CALL_FUNCTION
и LOAD_GLOBAL
. Вы можете сократить LOAD_GLOBAL
, определив локальное имя для False:
>>> test = lambda t,False=False : t.startswith('customernum') is False
>>> dis.dis(test)
1 0 LOAD_FAST 0 (t)
3 LOAD_ATTR 0 (startswith)
6 LOAD_CONST 0 ('customernum')
9 CALL_FUNCTION 1
12 LOAD_FAST 1 (False)
15 COMPARE_OP 8 (is)
18 RETURN_VALUE
Но что, если мы просто отбросим тест 'is' полностью?:
>>> test = lambda t : not t.startswith('customernum')
>>> dis.dis(test)
1 0 LOAD_FAST 0 (t)
3 LOAD_ATTR 0 (startswith)
6 LOAD_CONST 0 ('customernum')
9 CALL_FUNCTION 1
12 UNARY_NOT
13 RETURN_VALUE
Мы свернули LOAD_xxx
и COMPARE_OP
с простым UNARY_NOT
. «Неверно», безусловно, не способствует производительности.
Теперь, что, если мы сможем сделать какое-то грубое исключение строки, вообще не обращаясь ни к каким вызовам функций. Если первый символ строки не является 'c', он не будет начинаться с (customernum). Давайте попробуем это:
>>> test = lambda t : t[0] != 'c' and not t.startswith('customernum')
>>> dis.dis(test)
1 0 LOAD_FAST 0 (t)
3 LOAD_CONST 0 (0)
6 BINARY_SUBSCR
7 LOAD_CONST 1 ('c')
10 COMPARE_OP 3 (!=)
13 JUMP_IF_FALSE 14 (to 30)
16 POP_TOP
17 LOAD_FAST 0 (t)
20 LOAD_ATTR 0 (startswith)
23 LOAD_CONST 2 ('customernum')
26 CALL_FUNCTION 1
29 UNARY_NOT
>> 30 RETURN_VALUE
(Обратите внимание, что использование [0] для получения первого символа строки не создает срез - это на самом деле очень быстро.)
Теперь, если предположить, что строк, начинающихся с 'c', немного, фильтр черновой обработки может удалить строку, используя все довольно быстрые инструкции. Фактически, проверяя «t [0]! = 'C'» вместо «not t [0] == 'c'», мы спасаем себя от посторонних UNARY_NOT
инструкций.
Итак, используя это обучение по оптимизации ярлыков, я предлагаю изменить этот код:
while sline.startswith("customernum: ") is False:
sline = txtdb.readline()
while sline.startswith("customernum: "):
... do the rest of the customer data stuff...
К этому:
for sline in txtdb:
if sline[0] == 'c' and \
sline.startswith("customernum: "):
... do the rest of the customer data stuff...
Обратите внимание, что я также удалил вызов функции .readline () и просто перебрал файл, используя "for sline in txtdb".
Я понимаю, что Алекс полностью предоставил другой код для поиска этой первой строки 'customernum', но я постараюсь оптимизировать в общих рамках вашего алгоритма, прежде чем вытаскивать большие, но неясные пистолеты для чтения блоков.