Найти - Пользователи
Полная версия: Условные операторы, вопрос стиля
Начало » Python для новичков » Условные операторы, вопрос стиля
1
nJLyTo
Здравствуйте, давно интересовался, имеет ли право на существования форма записи условий, рассмотренная мною ниже.

Есть прогромма, которая имеет два списка: exc_list- отвечает за список сайтов, type_list- флаг, который определяет с каким типом списка мы сейчас работаем. Если type_list = 0, то это белый список, type_list = 1 черый. В зависимости от типа списка, мы должны разрешать или запрещать переход по url'у. Вот как это должно выглядеть:
exc_list = [u'mail.ru',u'yandex.ru',u'google.com',u'rambler.ru']
type_list = 1
host = u'rambler.ru'

if type_list:
# Black List
if host in exc_list:
print u'close'
else:
print u'connect'
else:
# White list
if host in exc_list:
print u'connect'
else:
print u'close'
1. Такая форма записи мне показалась не удобной, т.к. в этом случае код повторялся бы дважды, для каждого из условий. Тогда я решил записать это в одном условии:

if (host in exc_list and type_list) or (not host in exc_list and not type_list):
print u'close'
else:
print u'connect'
2. Хорошее решение, но слишком длиная запись, можно записать еще короче:

if ((None,True),(True,None))[type_list][host in exc_list]:
print u'connect'
else:
print u'close'
3. Это самая короткая форма записи. Могу ли я записывать так условия, как это отразится на скорости выполнения программы, если код выполняется в цикле?
Viper
Думаю самый нормальный вариант, конечно если я ничего не напутал :)
if type_list ^ host in exc_list: 
print u'close'
else:
print u'connect'
nJLyTo
Получаю ошибку:
TypeError: unsupported operand type(s) for ^: 'int' and 'unicode'
pasaranax
Тогда вот так:
if type_list ^ int(host in exc_list):
print u'connect'
else:
print u'close'
А теперь засечем время:
from timeit import Timer

t = Timer('''
exc_list = [u'mail.ru',u'yandex.ru',u'google.com',u'rambler.ru']
type_list = 1
host = u'rambler.ru'

if type_list:
# Black List
if host in exc_list:
pass
else:
pass
else:
# White list
if host in exc_list:
pass
else:
pass
''')

print t.timeit(100)

t = Timer('''
exc_list = [u'mail.ru',u'yandex.ru',u'google.com',u'rambler.ru']
type_list = 1
host = u'rambler.ru'

if (host in exc_list and type_list) or (not host in exc_list and not type_list):
pass
else:
pass
''')

print t.timeit(100)

t = Timer('''
exc_list = [u'mail.ru',u'yandex.ru',u'google.com',u'rambler.ru']
type_list = 1
host = u'rambler.ru'

if ((None,True),(True,None))[type_list][host in exc_list]:
pass
else:
pass
''')

print t.timeit(100)

t = Timer('''
exc_list = [u'mail.ru', u'yandex.ru', u'google.com', u'rambler.ru']
type_list = 0
host = u'rambler.ru'


if type_list ^ int(host in exc_list):
pass
else:
pass
''')

print t.timeit(100)
результат:
0.0046329498291
7.9870223999e-05
0.00012993812561
0.000120878219604

Вывод: второй вариант самый быстрый

Я тоже за второй вариант, так как он самый наглядный, хоть и громоздкий. “Явное лучше неявного”
nJLyTo
Спасибо, именно такого ответа я и ждал!
Viper
Не обязательно приводить к инту, можно просто type_list ^ (host in exc_list).

На счёт скорости тоже можно поспорить, поскольку второй вариант даёт больший разброс по времени выполнения в зависимости от данных, и выигрывает у моего варианта только в 1 случае из 4 :) .

(host in exc_list and type_list) or (not host in exc_list and not type_list)
5.41210174561e-05
0.000151872634888
8.29696655273e-05
8.29696655273e-05

type_list ^ (host in exc_list)
5.48362731934e-05
5.69820404053e-05
6.19888305664e-05
5.91278076172e-05
Griffon
Мне второй вариант нравиться больше всего.
Только надо его изменить.
if (type_list and host in exc_list) or (not type_list and not host in exc_list):
print u'close'
else:
print u'connect'
Так очевидно быстрее будет.
Зачем нам по два раза выполнять проверку по списку в худшем случае? Лучше всегда по разу.
j2a
Я бы сделал так:
def check_host(host, host_list, list_type='black'):
"""
>>> check_host('mail.ru', ['mail.ru', 'yandex.ru'], 'white')
'connect'
>>> check_host('python.su', ['mail.ru', 'yandex.ru'], 'white')
'close'
>>> check_host('mail.ru', ['mail.ru', 'yandex.ru'], 'black')
'close'
>>> check_host('python.su', ['mail.ru', 'yandex.ru'], 'black')
'connect'
"""
assert list_type in ('black', 'white')
actions = {
# (host in hostlist, is_whitelist): action
(True, 'white'): 'connect',
(False, 'white'): 'close',
(False, 'black'): 'connect',
(True, 'black'): 'close',
}
action = actions.get((host in host_list, list_type))
return action
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB