2013-12-21 4 views
2

Я выполнял некоторые упражнения CodingBat с использованием Python, пока не наткнулся на проблему с моим предлагаемым решением.Если заявления Заказа

Ссылка для упражнения here

Я пытался решить ее, используя этот код:

def alarm_clock(day, vacation): 
    if vacation and day == 0 or day == 6: 
     return "off" 
    elif vacation and day != 0 and day != 6: 
     return "10:00" 
    if vacation == False and day == 0 or day == 6: 
     return "10:00" 
    elif vacation == False and day != 0 or day != 6: 
     return "7:00" 

Что происходит, что когда день 6 и отдых в False, то он возвращает «выключено» вместо "10:00". Можете ли вы поделиться светом здесь? Является ли одно из первых утверждений If оценочным значением «10:00»?

+1

В качестве побочного примечания вы не должны использовать 'vacation == False'; просто используйте 'not vacation'. (Есть некоторые люди, которые утверждают, что '== False' хороши, но (а) они ошибаются, (б) они хотели бы, чтобы вы использовали« отпуск == Истинный », а не просто« отпуск »в двух других и (c) они ошибаются. :)) – abarnert

+0

Кроме того, об этом может быть проще подумать с вложенными утверждениями. Во-первых, 'if vacation:' ... 'else:'. Затем внутри каждого из них 'if day == 0 or day == 6:' ... 'else:'. Это означает 10 строк кода вместо 8, но они более короткие строки, более очевидные и сложнее ошибиться (в частности, ваша ошибка никогда не может возникнуть именно так). – abarnert

+0

Или, иначе, делать 'weekday = day == 0 или day == 6', тогда вы можете писать« отпуск и будний день »,« отпуск, а не будний день »,« не отпуск и будний день »,« не отпуск, а не будний день » ', что, вероятно, даже более читаемо. – abarnert

ответ

0

Приоритет логического or ниже, чем приоритет and в Python

Таким образом, в строке здесь

if vacation and day == 0 or day == 6: 

до тех пор, как day == 6, все утверждение будет верным.

Так правильным было бы

if vacation and (day == 0 or day == 6): 
+0

Технически это логические операторы, а не побитовые. – smeso

+0

Да, вы правы, исправлено – albusshin

+0

@AlbusShin: Это не исправлено; вы все еще говорите о «поразрядке». – abarnert

2
vacation and day == 0 or day == 6 

оценивает как

(vacation and day == 0) or day == 6 

Так что, если ваш day == 6 затем пункт оценивает.

Вы можете вместо

vacation and (day == 0 or day == 6) 
+0

Почему я всегда думал, что это была полная противоположность ... Anywyas, спасибо за ваш быстрый ответ! – user3124364

+0

@ user3124364: поскольку любой, кто читает «более высокий приоритет» или «более связан» или почти любое другое описание в документах любого языка, не имеет представления о том, какое направление это на самом деле означает. Если вы напишете парсер или укусите эту ошибку достаточно времени в своей жизни, в конце концов это станет для вас очевидным, и вы тоже сможете написать документы, которые путают новичков. :) – abarnert

0

and принимает precedense к or. Меняем:

if vacation and day == 0 or day == 6: 

с

if vacation and (day == 0 or day == 6): 

или лучше и английский, как:

if vacation and day in [0, 6]: 

Так что я бы сделать его похожим на это, чтобы быть более читаемым

weekend = [0, 6] 
def alarm_clock(day, vacation): 
    if vacation: 
    return day in weekend and "off" or "10:00" 
    else: 
    return day in weekend and "10:00" or "7:00" 
3

Другие уже отбросил приоритет логических операторов.Может быть, вы могли бы рассмотреть рефакторинга ваши условия несколько, как это (что ИМХО отражает более красиво дерево решений):

if vacation: 
    if day == 0 or day == 6: #or if day in (0, 6) 
     return "off" 
    else: 
     return "10:00" 
else: 
    if day == 0 or day == 6: #or if day in (0, 6) 
     return "10:00" 
    else: 
     return "7:00" 

развивавших dimo414 Комментарий:

weekend = day in (0, 6) 
if vacation: 
    if weekend: 
     return "off" 
    else: 
     return "10:00" 
else: 
    if weekend: 
     return "10:00" 
    else: 
     return "7:00" 

Или даже:

weekend = day in (0, 6) 
if vacation: 
    return "off" if weekend else "10:00" 
else: 
    return "10:00" if weekend else "7:00" 
+0

Еще лучше, сохраните '(0, 6)' кортеж в переменной, тогда вы можете сказать «день в выходные» или что-то подобное. – dimo414

+1

@ dimo414 Очень хороший вход. – Hyperboreus

0

I подумайте, что самое ясное решение здесь - просто назвать ваши промежуточные значения:

weekend = day == 0 or day == 6 

Теперь ли вы оставить вещи структурированы как есть:

def alarm_clock(day, vacation): 
    if vacation and weekend: 
     return "off" 
    elif vacation and weekday: 
     return "10:00" 
    elif not vacation and weekend: 
     return "10:00" 
    elif not vacation and not weekend: 
     return "7:00" 

... или реорганизовать его в вложенными if заявления:

def alarm_clock(day, vacation): 
    if vacation: 
     if weekend: 
      return "off" 
     else: 
      return "10:00" 
    else: 
     if weekend: 
      return "10:00" 
     else: 
      return "7:00" 

... или реорганизовать его на более высоком логическом уровне:

def alarm_clock(day, vacation): 
    if vacation and weekend: 
     return "off" 
    elif vacation or weekend: 
     return "10:00" 
    else: 
     return "7:00" 

... сразу видно, что происходит, и эта проблема не может быть даже ари в первую очередь.

Это также позволяет избежать еще очень распространенная ошибка людей, где ДЭ-Моргану сочетание not с and или or только на полпути, и вы в конечном итоге с вещами, как not a and b, когда вы имели в виду not a and not b.

И это делает ваш код более надежным для расширения - если позже вы решите, например, запустить свой код в стране, которая начинает нумерацию недель с понедельника вместо воскресенья, вам нужно изменить только одну строку кода вместо четырех разные строки (и четыре строки почти достаточно, чтобы гарантировать, что вы получите один из них неправильным ...).

+0

Отличный ответ.Единственное, что я (очень лично) не считаю очень удобным, это последний фрагмент кода. Когда у вас есть 4 случая (выходные или нет, отпуск или нет), я предпочитаю записывать все четыре случая, даже если два из них приводят к одинаковому значению (или n случаев с результатами m). Проблема в том, что 'elif' является скрытым' не (отпуск и выходные), а (отпуск или выходные) ', который не так просто читать (и, как говорится, код читается чаще, чем написан). Особенно «незамедлительно очевидная» часть пересекает Аида здесь. – Hyperboreus

+0

@Hyperboreus: Я хочу сказать, что если вы используете переменную с красивым именем вместо копирования и вставки условия, независимо от того, как вы структурируете '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' Поэтому я показал как можно больше способов структурирования 'if' ', как я мог думать, не пытаясь понять, в каком из них лучше или хуже. – abarnert

Смежные вопросы