Переопределение метода bool() для пользовательского класса
Ошибка: не удается заставить bool(myInstance)
возвращать False
в Python 2.6
Я пытаюсь реализовать поведение, при котором вызов bool(myInstance)
возвращает False
, а также чтобы экземпляр myInstance
оценивался как False
в условных операторах (таких как if
, or
, and
). Я знаю, как переопределять операторы сравнения (>
, <
, =
), но у меня возникла проблема с переопределением метода __bool__()
.
В своем коде я пробовал следующее:
class test:
def __bool__(self):
return False
myInst = test()
print bool(myInst) # выводит "True"
print myInst.__bool__() # выводит "False"
Тем не менее, при вызове bool(myInst)
результатом является True
, хотя ожидается False
. Обращаю внимание, что при прямом вызове myInst.__bool__()
возвращается правильное значение False
.
Как это исправить? Я использую Python 2.6.
Спасибо за любые предложения!
5 ответ(ов)
Данный код написан для Python 2.x, так как в этой версии вы переопределяете метод __nonzero__
для определения истинности объекта. В Python 3.x вы должны использовать метод __bool__
вместо __nonzero__
. Вот как это будет выглядеть в Python 3.x:
class test:
def __bool__(self):
return False
Таким образом, если вы используете Python 3.x, то имейте в виду, что нужно переопределять именно __bool__
.
Если вы хотите, чтобы ваш код оставался совместимым с Python 3, вы можете сделать что-то вроде этого:
class Test:
def __bool__(self):
return False
__nonzero__ = __bool__
В данном примере мы определяем метод __bool__
, который возвращает False
. В Python 2 есть также метод __nonzero__
, который необходимо переопределить для получения аналогичного поведения. Мы присваиваем __nonzero__
к __bool__
, чтобы поддерживать совместимость с обеими версиями Python. Это позволит вашему коду работать как в Python 2, так и в Python 3 без изменений в логике.
Если ваш класс test
имеет поведение, аналогичное списку, определите метод __len__
, чтобы bool(myInstanceOfTest)
возвращал True
, если в нем есть один или более элементов (непустой список), и False
, если элементов нет (пустой список). Это сработало для меня.
Вот пример реализации:
import heapq
class MinPriorityQueue(object):
def __init__(self, iterable):
self.priorityQueue = list(iterable) # Исправлено на list для правильной инициализации
heapq.heapify(self.priorityQueue)
def __len__(self):
return len(self.priorityQueue)
# Примеры использования
>>> bool(MinPriorityQueue([]))
False
>>> bool(MinPriorityQueue([1, 3, 2]))
True
В этом примере, если вы создаете экземпляр класса MinPriorityQueue
с пустым списком, результат bool()
будет False
. Если вы добавите элементы, как в примере с [1, 3, 2]
, результат будет True
.
Похожим образом, как и Джон Ла Руй, я использую следующий код:
class Test(object):
def __bool__(self):
return False
def __nonzero__(self):
return self.__bool__()
В этом примере класс Test
определяет оба метода: __bool__
для Python 3 и __nonzero__
для Python 2. Метод __bool__
возвращает False
, что означает, что экземпляры этого класса будут восприниматься как False
в контекстах, где ожидается булевое значение, например, в условных выражениях. Метод __nonzero__
используется в Python 2 для той же цели.
Однако стоит отметить, что если вы планируете работать только с Python 3, вы можете не определять метод __nonzero__
, так как он не поддерживается в Python 3. В этом случае достаточно лишь метода __bool__
.
Для совместимости с Python3 вы можете использовать следующий код (я как раз этого искал):
class test(object):
def __bool__(self):
return False
__nonzero__ = __bool__
Единственная проблема заключается в том, что вам нужно повторять присваивание __nonzero__ = __bool__
каждый раз, когда вы изменяете __bool__
в подклассах. В противном случае __nonzero__
будет унаследован из суперкласса. Вы можете попробовать следующий код:
from builtins import object # требует установки!
class test(object):
def __bool__(self):
return False
__nonzero__ = __bool__
Этот вариант должен работать (не подтверждено), или же вы можете написать метакласс самостоятельно.
UnicodeEncodeError: 'ascii' кодек не может закодировать символ u'\xa0' на позиции 20: номер не в диапазоне (128)
Разница между старыми и новыми классами в Python?
Имеет ли Python "приватные" переменные в классах?
IndentationError: неверный отступ, не соответствует ни одному уровню внешнего отступа, хотя отступ выглядит корректно
В чем разница между __init__ и __call__?