Python сравнение с None

Ответ:

Если любой объект не None сравнить (==) с объектом None, то результат будет False

НО: есть способ создать пользовательский объект, при сравнении которого с None мы получим True.

Обсуждение:

Сравнение с None -
например для string всегда ли возвращает True?

current_word = None
 if current_word == word: // ??

Судя по коду отсюда автор как раз рассчитывает на True. Но какие ещё бывают особенности?

humanmashine's picture

Не понял вопрос. Но всёже постараюсь ответить....
Если любой объект не None сравнить с объектом None, то результат будет False. В приведённой ссылке автор никак не расчитывает на выполнение условия. Дело в том, что None - это как бы "ничего" а ничего иногда интерпретируется как False.
Автор примера для Hadoop нарушил дзен Питона и сделал неочевидный шаг. Чтобы не выводить первый раз строку "None 0" он вставил условие:

if current_word:
            # записывает результат в стандартный поток вывода
            # опять же разделяя значения табом.
            print '%s\t%s' % (current_word, current_count) 

Условие не выполнится, так как current_word = None.

Более правильной (очевидной) проверкой условия является ли объект (скажем test) None выглядит, к примеру так:

if test is not None:
    #делаем что-нибудь
    pass
vedro-compota's picture

ок. спасибо за это пояснение - оно ценно - я даже не обратил внимания на строку

if current_word:

теперь ясно что это условие "работает" только один раз.

Но мой вопрос был именно по сравнению методом "==" с None - и оно имеет место в первой итерации цикла в строке:

current_word = None # изначально 
current_count = 0
word = None
 
# input comes from STDIN
for line in sys.stdin:
#.......
#...........
#..................
if current_word == word: # каков ответ в первой итерации
 # когда current_word ещё равен None ???
   current_count += coun

_____________
матфак вгу и остальная классика =)

humanmashine's picture

теперь ясно что это условие "работает" только один раз.

Скорее "не сработает" только один раз. )))
---
Касательно сравнение оператором "==", как я уже говорил:

Если любой объект не None сравнить с объектом None, то результат будет False.

vedro-compota's picture

ага....я не заметил строки:

current_count = count

которая выполнится в случае False и таким образом для первой итерации всё будет нормально.

Ещё помучаем знатока

Итак -

Если любой объект не None сравнить с объектом None, то результат будет False.

уточним как

Если любой объект не None сравнить (==) с объектом None, то результат будет False.

и можно было бы вынести в топик (вверху) но вот проблема
утверждают, что:

You can have custom classes where my_var == None will return True

то есть можно забомбить пользовательский класс, где

class Negator(object):
    def __eq__(self,other):
        return not other

thing = Negator()
print thing == None    #True
print thing is None    #False 

(отсюда: stackoverflow.com/questions/14247373/python-none-comparison-should-i-use-is-or)

Как быть и что происходит?

_____________
матфак вгу и остальная классика =)

humanmashine's picture

Вы опять невнимательно посмотрели код. Дело в том, что и должно посчитаться один раз, если их всего два.

# разбиваем каждую по символу таба
    # чтобы получить ключ и значение (число вхождений)
    word, count = line.split('\t', 1)
 
    # пытаемся перевести строку в число (число вхождений)
    try:
        count = int(count)
    except ValueError:
        # если перевести не получилось
        # то просто игнорируем эту строку и
        continue # продолжаем выполнение

В коде выше, мы не только считываем слово, но и число, которое в примере равно 1. Значит по-умолчанию счётчик равен 1. Если слово встречается всего два раза, то мы должны потом накрутить счётчик всего один раз.

vedro-compota's picture

должно посчитаться один раз, если их всего два.

верно)
А что а насчёт возвращаемого True здесь:

class Negator(object):
    def __eq__(self,other):
        return not other
 
thing = Negator()
print thing == None    #True
print thing is None    #False

Это из-за того что переопеределена функция сравнения. да?

_____________
матфак вгу и остальная классика =)

humanmashine's picture

По поводу определения пользовательских классов.
Действительно, операцию сравнения "==" можно переопределить, тем самым добиться иного поведения. Но если вы хотите или кто-то другой чтобы ваш объект был как None, то может не надо этому противиться. ))))
Хотя, чтобы избежать этого с объектом None, как я говорил ранее, лучше использовать выражение is, которое ведёт себя в общем случае так: возвращает истинну в случае с x is y, если x тот же объект что и y. Пример:

class A:
    u = "ololo"

a = A         # Присваиваем сам объект класса - сам класс
b = A        
if a is b:             # True так как "a" тот же объект что и "b"
    print("True1")   # Выведет True1
a = A()     # Создаём экземпляр класса
if a is b:             # Flase так как "a" - не тот же объект что и "b"; "a"-экземпляр "b"-сам класс
    print("True2")  # Не выполнится
a=A()
b=A()
if a is b:             # Flase так как "a" - не тот же объект что и "b"; "a" и"b"- это разные экземпляры A
    print("True3")  # Не выполнится
b = a          # теперь a и b это один объект (в python все переменные ссылки)
if a is b:            # True так как a и b один и тотже экземпляр класа A
    print("True4")  # Выполнится - выведет True4

Исходя из вышесказанного, если вам необходимо проверить что объект ТОЧНО не является объектом None, то используйте ранее описанный пример:

if test is not None:
    #делаем что-нибудь
    pass
vedro-compota's picture

благодарю за качественный ответ. )

_____________
матфак вгу и остальная классика =)

vedro-compota's picture

Прошу подсказать здесь: http://fkn.ktu10.com/?q=node/5836

И на досуге комментировать что-то наиболее важное из списка, который теперь видимо будет постоянно пополняться: http://fkn.ktu10.com/?q=node/5836

_____________
матфак вгу и остальная классика =)