Это Pythonic использовать bools как ints?

False эквивалентен 0, а True эквивалентен 1, поэтому можно сделать что-то вроде этого:

def bool_to_str(value):
    """value should be a bool"""
    return ['No', 'Yes'][value]

bool_to_str(True)

Обратите внимание, что значение bool, но используется как int.

Является ли этот вид использования Pythonic или его следует избегать?

Ответ 1

Я буду странным голосом (так как все ответы осуждают использование факта False == 0 и True == 1, как гарантирует язык), поскольку я утверждаю, что использование этого факта для упрощения кода отлично.

Исторически логические операции true/false обычно используют 0 для false и 1 для true; в течение жизненного цикла Python 2.2 Гвидо заметил, что слишком много модулей началось с заданий, таких как false = 0; true = 1, и это привело к созданию шаблона и бесполезной вариации (последняя из-за того, что капитализация истинных и ложных была повсюду - некоторые использовались all-caps, некоторые все-строчные, некоторые cap-initial) и поэтому ввел подкласс bool int и его константы True и False.

В то время было довольно много отклика, поскольку многие из нас боялись, что новый тип и константы будут использоваться новичками Python для ограничения языковых возможностей, но Гвидо был непреклонен, что мы просто пессимистичны: никто никогда не поймет Python так плохо, например, чтобы избежать естественного использования False и True в качестве индексов списка или в суммировании или других таких совершенно ясных и полезных идиом.

Ответы на этот вопрос доказывают, что мы были правы: как мы опасались, возникло полное непонимание ролей этого типа и констант, и люди избегают и, что еще хуже, убеждают других избегать совершенно естественных конструкций Python в пользу бесполезных колебаний.

Борясь с волнением такого недоразумения, я призываю всех использовать Python как Python, not, пытаясь загнать его в форму других языков, функциональность и предпочитаемый стиль которых совершенно разные. В Python True и False равны 99,9%, как 1 и 0, отличаются исключительно формой str(...) (и тем самым repr(...)) - для любой другой операции, кроме строкования, просто не стесняйтесь использовать их без искажений. Это относится к индексированию, арифметике, битовым операциям и т.д. И т.д. И т.д.

Ответ 2

Я с Алексом. False==0 и True==1, и в этом нет ничего плохого.

Тем не менее, в Python 2.5 и позже я напишу ответ на этот конкретный вопрос, используя условное выражение Python:

def bool_to_str(value):
  return 'Yes' if value else 'No'

Таким образом, нет требования, чтобы аргумент был фактически bool - так же, как if x: ... принимает любой тип для x, функция bool_to_str() должна поступать правильно, когда она передается None, строка, a список или 3.14.

Ответ 3

конечно:

def bool_to_str(value):
    "value should be a bool"
    return 'Yes' if value else 'No'

более читабельна.

Ответ 4

В некоторых случаях ваш код кажется неточным:

>>> def bool_to_str(value):
...     """value should be a bool"""
...     return ['No', 'Yes'][value]
...
>>> bool_to_str(-2)
'No'

И я рекомендую использовать только условный оператор для удобочитаемости:

def bool_to_str(value):
    """value should be a bool"""
    return "Yes" if value else "No"

Ответ 5

На самом деле это признак языка False == 0 и True == 1 (он не зависит от реализации): Является False == 0 и True == 1 в Python - деталь реализации или она гарантирована языком?

Однако я согласен с большинством других ответов: есть более читаемые способы получить тот же результат, что и ['No', 'Yes'][value], используя … if value else … или словаря, которые имеют соответствующие преимущества намека и утверждая, что value является булевым.

Кроме того, … if value else … следует обычному соглашению, что не-0 имеет значение True: он также работает даже тогда, когда value == -2 (значение True), как намекнул георгин. В этом случае подходы списка и диктата не столь надежны, поэтому я бы не рекомендовал их.

Ответ 6

Использование bool как int вполне нормально, потому что bool является подклассом int.

>>> isinstance(True, int)
True
>>> isinstance(False, int)
True

О вашем коде: добавление его в однострочную функцию похоже на верх. Читателям необходимо найти источник или документы функции и прочитать его (имя функции не говорит вам много). Это прерывает поток. Просто поместите его в строку и не используйте список (построенный во время выполнения), используйте кортеж (построенный во время компиляции, если значения являются константами). Пример:

print foo, bar, num_things, ("OK", "Too many!)[num_things > max_things]

Ответ 7

Лично я думаю, что это зависит от того, как вы хотите использовать этот факт, вот два примера

  • Просто используйте boolean, поскольку условный оператор в порядке. Люди делают это все время.

    a = 0
    if a:
        do something
    
  • Однако скажите, что вы хотите подсчитать, сколько элементов прошло успешно, код может быть не очень дружелюбным для чтения другими людьми.

    def succeed(val):
        if do_something(val):
            return True
        else:
            return False
    
    count = 0
    values = [some values to process]
    for val in values:
        count += succeed(val)
    

Но я вижу, что производственный код выглядит следующим образом.

all_successful = all([succeed(val) for val in values])
at_least_one_successful = any([succeed(val) for val in values])
total_number_of_successful = sum([succeed(val) for val in values])