Может ли цикл for с if работать как if с elif и else ветками? - PullRequest
0 голосов
/ 08 сентября 2018

У меня есть код вроде:

if 'x' in longstr:
    longstr = longstr.replace('x', '')
elif 'y' in longstr:
    longstr = longstr.replace('y', '')
elif 'z' in longstr:
    longstr = longstr.replace('z', '')
else:
    longstr = longstr.replace('foo', '')

Если бы я хотел использовать цикл for вместо:

for char in ['x','y','z']:
    if char in longstr:
        longstr = longstr.replace(str, '')
        break

Как я могу заменить else: окончательный / общий случай в примере if..elif..else выше (else: longstr = longstr.replace('xyz', ''))?

И, прежде всего, какая из двух форм работает лучше?

1 Ответ

0 голосов
/ 08 сентября 2018

Просто добавьте набор else: в цикл for:

for char in ['x','y','z']:
    if char in longstr:
       longstr = longstr.replace(char, '')
       break
else:
    longstr = longstr.replace('xyz', '')

Набор else в цикле for выполняется только в том случае, если цикл for завершился без преждевременного завершения break. См. Документацию for :

Когда элементы исчерпаны [...] , набор в предложении else, если он присутствует, выполняется и цикл завершается.

Оператор break, выполняемый в первом наборе, завершает цикл без выполнения набора предложения else.

Чтобы увидеть, какой из них работает лучше, вам нужно рассчитать время, используя timeit. Однако, если вы не выполняете секцию критического кода в узком цикле , пожалуйста, придерживайтесь if...elif...else, так как комбо for...else не очень хорошо известно, и многие программисты не будут знать о семантике, ломающей их голову , Более того, для вашего игрушечного примера вы все равно будете использовать регулярные выражения в тесте if или цикле for.

Сроки этих двух тривиальных примеров:

>>> from timeit import Timer
>>> def example1(longstr):
...     if 'x' in longstr:
...         longstr = longstr.replace('x', '')
...     elif 'y' in longstr:
...         longstr = longstr.replace('y', '')
...     elif 'z' in longstr:
...         longstr = longstr.replace('z', '')
...     else:
...         longstr = longstr.replace('foo', '')
...
>>> def example2(longstr):
...     for char in ['x','y','z']:
...         if char in longstr:
...            longstr = longstr.replace(char, '')
...            break
...     else:
...         longstr = longstr.replace('xyz', '')
...
>>> from string import ascii_lowercase
>>> from random import choice
>>> teststring = ''.join([choice(ascii_lowercase) for _ in range(10000)])
>>> for ex in (example1, example2):
...     count, total = Timer('ex(s)', 'from __main__ import teststring as s, ex').autorange()
...     print(f'{ex.__name__}: {total/count * 1000000}µs')
...
example1: 15.999997949984389µs
example2: 16.788980951241683µs

показывает, что между ними всего 1,8 микросекунда . Если я перезапущу образцы несколько раз, один или другой пример выиграет с такими же чрезвычайно маленькими полями. Это на самом деле не делает один или другой самый быстрый, поэтому вы можете считать их равными в этом случае .

Однако, если у вас есть необходимость микрооптимизации такого раздела, вам нужно сделать свои собственные настройки времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...