Проверка условия, которая дает один и тот же результат для True и True, что может создать впечатление, что они одинаковы.

Из основ мы изучаем различные типы переменных: целые числа, числа с плавающей запятой, строки, логические значения и т. д. Строка — это не то же самое, что логическое значение, и наоборот. В Python True не равно True.

Однако существует проверка условия, которая дает один и тот же результат для True и True, что может создать впечатление, что они одинаковы.

>>> type(True)
(<class 'bool’>
>>>
>>> if(True): print(’ok’)
...
ok
>>>
>>> type(’True’)
<class 'str’>)
>>>
>>> if(’True’): print(’ok’)
...
ok

Это то, что я называю «Ловушка ложных срабатываний». Теперь вы можете быть введены в заблуждение, полагая, что «Верно» может заменить Верно и что «Ложь» может заменить Ложь. .

Что случилось?

Проблема связана с проверкой условия, которая просто проверяет, является ли переменная истинной ИЛИ, если она существует и не является нулевой, 0 или пустой. True — это логическое значение true, поэтому оно пройдет. "Истина" – это непустая строка, поэтому она также будет принята.

Имея это в виду, вы можете легко сделать вывод, что «False» пройдет, потому что это непустая строка, такая же, как «Medium» или строка с пробелами «». Определена функция check(var) для лучшей иллюстрации тестов.

>>>#Defining the function
>>> def check(var):
...    if(var):
...       return 'ok'
...    else:
...       return 'not ok'
>>>
>>> check('False')
'ok'
>>> check('Medium')
'ok'
>>> check(' ')
'ok'

Итак, что же на самом деле неверно?

Любое число, отличное от 0, любая непустая строка или список будут считаться истинными в этой проверке условия. Так проще посмотреть с противоположной стороны: что НЕ ПРОЙДЕТ при проверке этого условия?

>>> check(False)  #boolean
'not ok'
>>> check(0)    #integer
'not ok'
>>> check(0.0)  #float
'not ok'
>>> check([])   #list
'not ok'
>>> check({})  #dictionary
'not ok'
>>> check(None)  #none
'not ok'
>>> check('')   #string
'not ok'

Пустой объект

Осторожно: пустой словарь не прошел, однако пустой объект пройдет.

>>> class Animal(object):
...     pass
...
>>> Dog = Animal()
>>> type(Dog)
<class '__main__.Animal'>
>>> 
>>> check(Dog)
'ok'

Неопределенный отличается

Пустая строка или объект NoneType — это не то же самое, что undefined. Если переменная никогда ранее не инициализировалась, та же проверка вернет ошибку.

>>> check(ABC)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'ABC' is not defined

Избегайте ловушки

Перед созданием проверки условия проведите обширные тесты, чтобы убедиться, что они дают ожидаемый результат. А в случае использования проверок условий в существующих библиотеках убедитесь, что вы знаете, как они работают.

Проверка условия в этом сообщении используется Django для проверки того, является ли DEBUG значением True или False. Django предотвращает NameError, инициализируя DEBUG=False в своей основе. Обычно мы переопределяем его для разработки.

def debug_print(self, msg):
"""Print 'msg' to stdout if the global DEBUG (taken from the DISTUTILS_DEBUG environment variable) flag is true."""
   from distutils.debug import DEBUG
   if DEBUG:
      print(msg)
      sys.stdout.flush()

Для вашей проверки условия, возможно, вы хотите, чтобы пустые объекты были False, или целые числа и числа с плавающей запятой были True, даже если значение равно нулю. Поэтому вам следует создать более комплексную функцию для проверки всех этих условий.

Undefined для возврата False вместо ошибки

Чтобы заставить неопределенную переменную возвращать False вместо этого или генерировать NameError, используйте try…, кроме:

try:
   check(var)
except NameError:
   False

Пустой объект для возврата False вместо True

Чтобы пустой объект возвращал значение False, проверьте его атрибут __dict__. Пустой объект будет иметь пустой словарь и, следовательно, вернет False. Непустые объекты, списки и словари возвращают значение True по умолчанию.

if hasattr(var, '__dict__'):
   check(var.__dict__)

Числовые переменные всегда возвращают False

Если вы хотите, чтобы числовые переменные возвращали False независимо от их значения:

if type(var) in [int,float]:
   False

Строка с пробелами только для возврата False

Пустая строка вернет False, но если в ней есть пробелы, она вернет True. Чтобы сделать его False, используйте функцию strip().

>>> SPAC = '   '
>>> check(SPAC)
'ok'
>>> check(SPAC.strip())
'not ok'

Скомпилированная проверка состояния

В заключение давайте создадим пример для одной скомпилированной функции, если мы хотим проверить, является ли значение True или False, со следующими условиями:

  • существующие числовые переменные возвращают False, какое бы значение они ни имели.
  • объекты, кортежи, списки и словари возвращаются в соответствии с их первым значением.
  • строки, в которых есть только пробелы для возврата False.
  • строковая переменная со значением ‘True’, чтобы вернуть True.
  • неопределенные переменные вместо ошибки возвращают False.

В отличие от предыдущей простой функции check(var), MyTrueCheck(var) имеет более строгие ограничения и отдает предпочтение возврату False, а не Верно.

Например, список вернет True только в том случае, если его первый элемент имеет значение: True или ‘trUe’. Раньше любой непустой список возвращал значение True.

>>> L1 = []
>>> MyTrueCheck(L1)
False
>>> L2 = ['one', ' true ']
>>> MyTrueCheck(L2)
False
>>> L3 = [' tRUe  ', 'two']
>>> MyTrueCheck(L3)
True

В завершение объект вернет False, если только первое значение в его словаре не эквивалентно True.

>>> class Country(object):
...     pass
...
>>> Spain = Country()
>>> MyTrueCheck(Spain)
False
>>> Spain.key1 = ' true '
>>> MyTrueCheck(Spain)
True

И вот оно. Спасибо за чтение.

Больше контента на plainenglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку здесь.