В python есть какое-то отображение для возврата "False value" типа?

Я ищу какую-то функцию отображения f() которая делает что-то похожее на это:

f(str) = ''
f(complex) = 0j
f(list) = []

Это означает, что он возвращает объект типа, который оценивается как False при передаче в bool.

Существует ли такая функция?

Ответы

Ответ 1

Нет, такого сопоставления нет. Не каждый тип объекта имеет фальшивое значение, а другие - более одного. Поскольку значение истины класса может быть настроено с __bool__ метода __bool__, класс теоретически может иметь бесконечное количество (разных) фальшивых экземпляров.

Тем не менее, большинство встроенных типов возвращают свою фальшивую ценность, когда их конструктор вызывается без аргументов:

>>> str()
''
>>> complex()
0j
>>> list()
[]

Ответ 2

Нет, и вообще, такой ценности не может быть. Модель данных Python довольно свободна в отношении того, как может быть реализована истинностная ценность типа:

object.__bool__(self)

Вызывается для реализации тестирования ценности истины и встроенной операции bool(); должен возвращать False или True. Когда этот метод не определен, __len__(), если он определен, и объект считается истинным, если его результат отличен от нуля. Если класс не определяет ни __len__() ни __bool__(), все его экземпляры считаются истинными.

Поэтому рассмотрим:

import random
class Wacky:
    def __bool__(self):
        return bool(random.randint(0,1))

Что должно вернуть f(Wacky)?

Ответ 3

Не все типы имеют такую ценность для начала. У других может быть много таких ценностей. Самый правильный способ сделать это - создать тип-значение-dict, потому что тогда вы могли бы проверить, был ли данный тип в dict вообще, и вы могли бы выбрать, какое значение является правильным, если есть несколько параметров, Недостатком, конечно, является то, что вам нужно каким-то образом зарегистрировать все интересующие вас типы.

Кроме того, вы можете написать функцию, используя некоторые эвристики. Если бы вы были очень осторожны в том, что вы передали в функцию, это, вероятно, будет иметь ограниченное применение. Например, все случаи, которые вы показываете, кроме complex представляют собой контейнеры, которые обобщаются с помощью cls().

complex действительно работает так же, но я упоминаю его отдельно, потому что int и float этого не делают. Поэтому, если ваша попытка с пустым конструктором завершится неудачей, вернув правдивый объект или подняв TypeError, вы можете попробовать cls(0). И так далее...

Обновить

@juanpa.arrivillaga ответ на самом деле предлагает умное обходное решение, которое будет работать для большинства классов. Вы можете расширить класс и принудительно создать экземпляр, который будет ложным, но в остальном идентичным исходному классу. Вы должны сделать это, расширяя, потому что методы __bool__ такие как __bool__, всегда смотрят на класс, а не на экземпляр. Существует также множество типов, где такие методы не могут быть заменены на экземпляре для начала. Как отмечается в комментарии @Aran-Fey, теперь вы можете выборочно вызывать object.__new__ или t.__new__, в зависимости от того, имеете ли вы дело с очень особым случаем (например, int) или нет:

def f(t):
    class tx(t):
        def __bool__(self):
            return False
    try:
        return object.__new__(tx)
    except TypeError:
        return tx.__new__(tx)

Это будет работать только на 99,9% классов, с которыми вы когда-либо сталкивались. Можно создать надуманный случай, который вызывает TypeError при передаче object.__new__ как int и не допускает версию t.__new__, но я сомневаюсь, что вы когда-нибудь найдете такую вещь в природе. См. Суть @Аран-Фей, чтобы продемонстрировать это.

Ответ 4

Это на самом деле называется элементом идентификации, а в программировании чаще всего рассматривается как часть определения моноида. В Python, вы можете получить его типа, используя mzero функцию в PyMonad пакете. Хаскелл называет это mempty.

Ответ 5

Нет такой функции, потому что это невозможно вообще. Класс может не иметь фальшивой стоимости или может потребовать реверсирования произвольно сложной реализации __bool__.

То, что вы могли бы сделать, сломав все остальное, - это построить новый объект этого класса и принудительно назначить его функцию __bool__ тому, который возвращает False. Хотя я подозреваю, что вы ищете объект, который в противном случае был бы действительным членом класса.

В любом случае, это очень плохая идея в классическом стиле.