В 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
. Хотя я подозреваю, что вы ищете объект, который в противном случае был бы действительным членом класса.
В любом случае, это очень плохая идея в классическом стиле.