Перетворити значення True / False, прочитане з файлу, у логічне значення


86

Я читаю True - Falseзначення з файлу, і мені потрібно перетворити його на логічне значення. В даний час він завжди перетворює його на, Trueнавіть якщо для значення встановлено значення False.

Ось MWEте, що я намагаюся зробити:

with open('file.dat', mode="r") as f:
    for line in f:
        reader = line.split()
        # Convert to boolean <-- Not working?
        flag = bool(reader[0])

if flag:
    print 'flag == True'
else:
    print 'flag == False'

file.datФайл в основному складається з одного рядка із значенням Trueабо Falseписьмовій всередині. Домовленість виглядає дуже заплутаною, оскільки це мінімальний приклад набагато більшого коду, і саме так я читаю в ньому параметри.

Чому flagзавжди перетворюється на True?


1
pip install str2bool
Symon

Відповіді:


100

bool('True')і bool('False')завжди повертати, Trueтому що рядки "True" і "False" не порожні.

Процитувавши великого чоловіка (і документацію Python ):

5.1. Перевірка цінності істини

Будь-який об'єкт може бути перевірений на істинність, використаний у стані if або while або як операнд булевих операцій нижче. Наступні значення вважаються помилковими:

  • ...
  • нуль будь-якого числового типу, наприклад, 0, 0L, 0.0, 0j.
  • будь-яка порожня послідовність, наприклад, '', (), [].
  • ...

Усі інші значення вважаються істинними - тому об'єкти багатьох типів завжди є істинними.

Вбудована boolфункція використовує стандартну процедуру перевірки істинності. Ось чому ви завжди отримуєте True.

Щоб перетворити рядок у логічну форму, потрібно зробити щось подібне:

def str_to_bool(s):
    if s == 'True':
         return True
    elif s == 'False':
         return False
    else:
         raise ValueError # evil ValueError that doesn't tell you what the wrong value was

23
Ви можете зробити це "героїчним" ValueError, роблячи raise ValueError("Cannot covert {} to a bool".format(s)).
SethMMorton

Вибравши цей, оскільки він не використовує зайвих пакетів. Дякую, хлопці!
Габріель

1
Що поганого в "зайвих пакетах"? Ви маєте на увазі ast? Це частина стандартної бібліотеки, тому насправді не є додатковою.
SethMMorton

4
це може бути безглуздим запитанням, але чому boolпросто не перетворює рядки Trueі Falseна логічні значення Trueі False? Здається, несумісна поведінка з тим, що intробить. Мені просто щиро цікаво, чому мої міркування хибні і чому іншим варіантом було рішення.
Charlie Parker

1
Коли б я не порівнював рядки, я люблю вирівнювати регістр (де це можливо). наприклад, я б використав: if s.upper () == 'TRUE': return True elif s.upper () == 'FALSE' return False
Білл Кідд

75

ви можете використовувати distutils.util.strtobool

>>> from distutils.util import strtobool

>>> strtobool('True')
1
>>> strtobool('False')
0

Trueзначення y, yes, t, true, onі 1; Falseзначення n, no, f, false, offі 0. Піднімається, ValueErrorякщо val - це щось інше.


22
Ще краще зробити bool(strtobool(my_string))виведення результату як
логічну

10
@AlexG божевільний, що викликана функція strtobool()насправді не повертаєbool
dericke

61

Використання ast.literal_eval:

>>> import ast
>>> ast.literal_eval('True')
True
>>> ast.literal_eval('False')
False

Чому прапор завжди перетворюється на True?

Непорожні рядки завжди є True у Python.

Пов’язане: Тестування цінності істини


Якщо NumPy є варіантом, то:

>>> import StringIO
>>> import numpy as np
>>> s = 'True - False - True'
>>> c = StringIO.StringIO(s)
>>> np.genfromtxt(c, delimiter='-', autostrip=True, dtype=None) #or dtype=bool
array([ True, False,  True], dtype=bool)

це може бути безглуздим запитанням, але чому boolпросто не перетворює рядки Trueі Falseна логічні значення Trueі False? Здається, несумісна поведінка з тим, що intробить. Мені просто щиро цікаво, чому мої міркування хибні і чому іншим варіантом було рішення.
Charlie Parker

2
ast.literal_eval ('false') видає виняток, який, на мою думку, робить це менш бажаним
Кріс,

@Chris Ви завжди можете обернути його навколо спроби, за винятком спеціальної функції, замість того, щоб використовувати її безпосередньо тоді.
Ашвіні Чаудхарі,

@HewwoCraziness Він аналізує лише вирази, а не будь-який випадковий код.
Ashwini Chaudhary

15

Найчистіше рішення, яке я бачив:

from distutils.util import strtobool
def string_to_bool(string):
    return bool(strtobool(str(string)))

Звичайно, для цього потрібен імпорт, але він має належну обробку помилок і вимагає написання (і тестування) дуже мало коду.


13

Я не пропоную це як найкращу відповідь, просто альтернативу, але ви також можете зробити щось на зразок:

flag = reader[0] == "True"

прапорець буде Trueчитачем ідентифікаторів [0] має значення "True", інакше буде False.


10

В даний час це оцінюється до, Trueоскільки змінна має значення. Тут є хороший приклад того, що відбувається, коли ви оцінюєте довільні типи як логічну.

Коротше кажучи, то , що ви хочете зробити , це ізолювати 'True'або 'False'рядок і запустити evalна ньому.

>>> eval('True')
True
>>> eval('False')
False

4
@samyi Небезпечно використовувати метод eval. stackoverflow.com/questions/1832940/…
M07

1
FYI. Це жахлива ідея, і ви ніколи не повинні використовувати її eval(). На мою думку, його слід вилучити з мови.
Nostalg.io

Це ДУЖЕ ДУЖЕ ПОРО, оскільки це недолік безпеки. Якщо ви використовуєте eval()необроблені дані з файлу, це означає, що кожен, хто має доступ до запису до цього файлу, може виконувати код на тому ж рівні дозволів, що і ваш сценарій.
Кіт Ріплі,

Крім того, якщо значення не мають точного написання python, наприклад eval('false'), eval('FALSE')це буде помилкою.
kev

5

Ви можете використовувати dict для перетворення рядка в логічний. Змініть цей рядок flag = bool(reader[0])на:

flag = {'True': True, 'False': False}.get(reader[0], False) # default is False

5

Якщо ви хочете не враховувати регістр, ви можете просто зробити:

b = True if bool_str.lower() == 'true' else False

Приклад використання:

>>> bool_str = 'False'
>>> b = True if bool_str.lower() == 'true' else False
>>> b
False
>>> bool_str = 'true'
>>> b = True if bool_str.lower() == 'true' else False
>>> b
True


2

Можна обійтися json.

In [124]: import json

In [125]: json.loads('false')
Out[125]: False

In [126]: json.loads('true')
Out[126]: True

2

Просто додамо, що якщо ваше значення істини може змінюватися, наприклад, якщо це вхідні дані з різних мов програмування або з різних типів, більш надійним методом буде:

flag = value in ['True','true',1,'T','t','1'] # this can be as long as you want to support

І більш ефективним варіантом буде (встановити пошук O (1)):

TRUTHS = set(['True','true',1,'T','t','1'])
flag = value in truths


0

Якщо вам потрібен швидкий спосіб перетворення рядків у bools (що функціонує з більшістю рядків), спробуйте.

def conv2bool(arg):
   try:
     res= (arg[0].upper()) == "T"
   except Exception,e:
     res= False
   return res # or do some more processing with arg if res is false


0

Використання диктовок для перетворення "True" у True:

def str_to_bool(s: str):
    status = {"True": True,
                "False": False}
    try:
        return status[s]
    except KeyError as e:
        #logging
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.