Использование IF, AND, OR вместе с операндом EQUAL вместе в Python

Я пытаюсь создать функцию, в которой заданное значение (переданное в виде строки) проверяется, чтобы увидеть, является ли число цифр 4 или 6, и что это число.

Мой первый импульс должен был пойти с этим кодом:

def number(x):
    if (len(x) == (4 or 6)) and x.isdigit():
        print "True"
    else:
        print "False"

Этот код выше только проходит первый тест ниже... Я не понимаю, почему он проходит это, но ни один из других тестов:

number("1234")

Только когда я отделю функции len(), он будет работать правильно.

def number(x):
    if (len(x) == 4 or len(x) == 6) and x.isdigit():
        print "True"
    else:
        print "False"


## Checks
number("1234")
number("123456")
number("abcd")
number("abcdef")
number("1")
number("a")

Приведенный выше код проходит все тесты.

Итак, мои вопросы:

  1. Что тут происходит?
  2. Есть ли способ написать более чистый код для этого?

Спасибо за помощь!

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

6 ответов

Решение

Это помогает изучить логику этой строки:

if (len(x) == (4 or 6)):

(4 or 6) предложение содержит логический or короткое замыкание. Значение 4 верно, поэтому он оценивается и возвращается == реляционное сравнение.

Способ, которым or работает то, что его левая часть вычисляется для логической истины, и ее значение возвращается, если оно истинно. Если левая часть не является логическим значением true, тогда правая часть вычисляется и возвращается ее значение.

Потому что левая сторона 4 or ... верно в логическом смысле, правая часть никогда не оценивается. Python даже не смотрит в прошлое 4 or, Если левое значение было ложным (например, 0), то правая часть or будет оцениваться.

Чтобы увидеть это в действии, попробуйте print 4 or 6, Выход будет 4.

Так как 4 является жестко закодированным истинным значением, ваше сравнение семантически такое же, как if (len(x) == 4) - то есть, поскольку 4 истинно, 6 никогда не оценивается.

Я полагаю, что вы действительно хотите знать, если len(x) 4 или 6. Вы можете поместить это в код несколькими способами:

if(len(x) == 4 or len(x) == 6 ...

if(len(x) in (4,6) ...

Вы можете использовать in Оператор вроде так:

def number(x):
    if len(x) in (4, 6) and x.isdigit():
    print "True"
else:
    print "False"

где in проверяет содержание в данном контейнере. Обратите внимание, что 4 or 6 сами по себе оценивать что-то нежелательное, вот почему ваш первый сегмент кода терпит неудачу. Вы можете проверить это на оболочке Python:

>>> 4 or 6
4

Вы, вероятно, хотели написать

if (len(x) in (4, 6)) and x.isdigit():

Вместо

if (len(x) == (4 or 6)) and x.isdigit(): 

Короткий ответ: len(x) in [4, 6] или же len(x) == 4 or len(x) == 6,

"или" является логическим или логическим выбором. (4 или 6) гарантированно разрешает ненулевое (истинное) значение. В этом случае он разрешается до 4, поэтому ваш тестовый пример проходит.

Я пойду вперед и отвечу

Есть ли способ написать более чистый код для этого?

Да. Вернуть логическое значение, а не печатать строку.

def number(x): 
    return len(x) in {4, 6} and x.isdigit()

print(number("1234")) # True

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

Беда в вашем or заявление.

Любое значение больше единицы оценивается как True когда вы положите его в условный. Так (4 or 6) всегда будет решаться на истину.

Вы могли бы использовать in утверждение выше или вы могли бы просто использовать два =="S:

if (len(x) == 4 or len(x) == 6) and x.isdigit()

Это немного словеснее, мне легче читать.

Другие вопросы по тегам