0

Переопределение метода bool() для пользовательского класса

18

Ошибка: не удается заставить 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 ответ(ов)

0

Данный код написан для Python 2.x, так как в этой версии вы переопределяете метод __nonzero__ для определения истинности объекта. В Python 3.x вы должны использовать метод __bool__ вместо __nonzero__. Вот как это будет выглядеть в Python 3.x:

class test:
    def __bool__(self):
        return False

Таким образом, если вы используете Python 3.x, то имейте в виду, что нужно переопределять именно __bool__.

0

Если вы хотите, чтобы ваш код оставался совместимым с Python 3, вы можете сделать что-то вроде этого:

class Test:
    def __bool__(self):
        return False
    __nonzero__ = __bool__

В данном примере мы определяем метод __bool__, который возвращает False. В Python 2 есть также метод __nonzero__, который необходимо переопределить для получения аналогичного поведения. Мы присваиваем __nonzero__ к __bool__, чтобы поддерживать совместимость с обеими версиями Python. Это позволит вашему коду работать как в Python 2, так и в Python 3 без изменений в логике.

0

Если ваш класс 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.

0

Похожим образом, как и Джон Ла Руй, я использую следующий код:

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__.

0

Для совместимости с 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__

Этот вариант должен работать (не подтверждено), или же вы можете написать метакласс самостоятельно.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь