Это 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])