Я думаю, що рішення Свена Марнаха та FJ є прекрасним, але це не швидше у моєму маленькому тесті. Це оптимізована версія Реймонда з використанням заздалегідь обчисленого set
:
$ python -m timeit -s "choices = set('abc')" \
-s "x = 'c'" \
-s "y = 'a'" \
"z, = choices - set(x + y)"
1000000 loops, best of 3: 0.689 usec per loop
Оригінальне рішення:
$ python -m timeit -s "x = 'c'" \
-s "y = 'a'" \
"if x == 'a' and y == 'b' or x == 'b' and y == 'a':" \
" z = 'c'" \
"elif x == 'b' and y == 'c' or x == 'c' and y == 'b':" \
" z = 'a'" \
"elif x == 'a' and y == 'c' or x == 'c' and y == 'a':" \
" z = 'b'"
10000000 loops, best of 3: 0.310 usec per loop
Зверніть увагу, що це найгірший можливий вхід для if
-значень, оскільки всі шість порівнянь доведеться випробувати. Тестування з усіма значеннями для x
і y
дає:
x = 'a', y = 'b': 0.084 usec per loop
x = 'a', y = 'c': 0.254 usec per loop
x = 'b', y = 'a': 0.133 usec per loop
x = 'b', y = 'c': 0.186 usec per loop
x = 'c', y = 'a': 0.310 usec per loop
x = 'c', y = 'b': 0.204 usec per loop
Варіант на set
основі показує однакову продуктивність для різних входів, але постійно в 2 - 8 разів повільніший . Причина полягає в тому, що на if
базі варіанта працює набагато простіший код: тести на рівність порівняно з хешуванням.
Я думаю, що обидва типи рішень цінні: важливо знати, що створення "складних" структур даних, таких як набори, коштує вам чогось у продуктивності - в той час як вони дають вам багато в читабельності та швидкості розробки . Складні типи даних також набагато кращі, коли код змінюється: легко розширити рішення на основі набору до чотирьох, п’яти, ... змінних, тоді як оператори if швидко перетворюються на кошмар обслуговування.