Уведомления

Группа в Telegram: @pythonsu

#1 Авг. 21, 2009 14:36:49

nJLyTo
От:
Зарегистрирован: 2008-11-11
Сообщения: 60
Репутация: +  0  -
Профиль   Отправить e-mail  

Условные операторы, вопрос стиля

Здравствуйте, давно интересовался, имеет ли право на существования форма записи условий, рассмотренная мною ниже.

Есть прогромма, которая имеет два списка: 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. Это самая короткая форма записи. Могу ли я записывать так условия, как это отразится на скорости выполнения программы, если код выполняется в цикле?



Офлайн

#2 Авг. 21, 2009 15:36:08

Viper
От:
Зарегистрирован: 2006-11-08
Сообщения: 137
Репутация: +  0  -
Профиль   Отправить e-mail  

Условные операторы, вопрос стиля

Думаю самый нормальный вариант, конечно если я ничего не напутал :)

if type_list ^ host in exc_list: 
print u'close'
else:
print u'connect'



Офлайн

#3 Авг. 21, 2009 15:45:09

nJLyTo
От:
Зарегистрирован: 2008-11-11
Сообщения: 60
Репутация: +  0  -
Профиль   Отправить e-mail  

Условные операторы, вопрос стиля

Получаю ошибку:

TypeError: unsupported operand type(s) for ^: 'int' and 'unicode'



Офлайн

#4 Авг. 21, 2009 16:04:39

pasaranax
От:
Зарегистрирован: 2009-06-13
Сообщения: 574
Репутация: +  0  -
Профиль   Отправить e-mail  

Условные операторы, вопрос стиля

Тогда вот так:

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

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

Я тоже за второй вариант, так как он самый наглядный, хоть и громоздкий. “Явное лучше неявного”



Отредактировано (Авг. 21, 2009 16:06:24)

Офлайн

#5 Авг. 21, 2009 16:40:31

nJLyTo
От:
Зарегистрирован: 2008-11-11
Сообщения: 60
Репутация: +  0  -
Профиль   Отправить e-mail  

Условные операторы, вопрос стиля

Спасибо, именно такого ответа я и ждал!



Офлайн

#6 Авг. 21, 2009 16:55:58

Viper
От:
Зарегистрирован: 2006-11-08
Сообщения: 137
Репутация: +  0  -
Профиль   Отправить e-mail  

Условные операторы, вопрос стиля

Не обязательно приводить к инту, можно просто 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



Офлайн

#7 Авг. 21, 2009 17:35:31

Griffon
От: Ukrain, Zaporozhie
Зарегистрирован: 2009-03-04
Сообщения: 324
Репутация: +  11  -
Профиль   Отправить e-mail  

Условные операторы, вопрос стиля

Мне второй вариант нравиться больше всего.
Только надо его изменить.

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'
Так очевидно быстрее будет.
Зачем нам по два раза выполнять проверку по списку в худшем случае? Лучше всегда по разу.



Офлайн

#8 Авг. 24, 2009 10:10:48

j2a
От:
Зарегистрирован: 2006-06-29
Сообщения: 869
Репутация: +  1  -
Профиль   Отправить e-mail  

Условные операторы, вопрос стиля

Я бы сделал так:

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



Отредактировано (Авг. 24, 2009 10:11:57)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version