Konvertiert den aus der Datei gelesenen True / False-Wert in einen Booleschen Wert


85

Ich lese einen True - FalseWert aus einer Datei und muss ihn in einen Booleschen Wert konvertieren. Derzeit wird es immer in konvertiert, Trueauch wenn der Wert auf gesetzt ist False.

Hier ist ein MWEvon dem, was ich zu tun habe versucht:

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'

Die file.datDatei besteht im Wesentlichen aus einer einzelnen Zeichenfolge mit dem Wert Trueoder darin Falsegeschrieben. Die Anordnung sieht sehr kompliziert aus, da dies ein minimales Beispiel aus einem viel größeren Code ist und ich so Parameter hineinlese.

Warum wird flagimmer konvertiert True?


1
pip install str2bool
Symon

Antworten:


99

bool('True')und bool('False')immer zurückkehren, Trueda die Zeichenfolgen 'True' und 'False' nicht leer sind.

Um einen großartigen Mann (und die Python- Dokumentation ) zu zitieren :

5.1. Wahrheitswertprüfung

Jedes Objekt kann auf seinen Wahrheitswert getestet werden, um es in einer if- oder while-Bedingung oder als Operand der folgenden Booleschen Operationen zu verwenden. Die folgenden Werte gelten als falsch:

  • Null von beliebigen numerischen Typs, zum Beispiel 0, 0L, 0.0, 0j.
  • jede leere Sequenz, zum Beispiel, '', (), [].

Alle anderen Werte gelten als wahr - Objekte vieler Typen sind also immer wahr.

Die eingebaute boolFunktion verwendet das Standardverfahren zum Testen der Wahrheit. Deshalb bekommen Sie immer True.

Um einen String in einen Booleschen Wert umzuwandeln, müssen Sie Folgendes tun:

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

22
Sie könnten es zu einem "Helden" machen, ValueErrorindem Sie es tun raise ValueError("Cannot covert {} to a bool".format(s)).
SethMMorton

Wählen Sie dieses aus, da keine zusätzlichen Pakete verwendet werden. Danke Leute!
Gabriel

1
Was ist los mit "zusätzlichen Paketen"? Beziehen Sie sich auf ast? Es ist Teil der Standardbibliothek, also nicht wirklich extra.
SethMMorton

4
Es mag eine dumme Frage sein, aber warum boolkonvertiert man die Strings Trueund nicht einfach Falsein die booleschen Werte Trueund False? Scheint inkonsistentes Verhalten von dem zu sein, was inttut. Ich bin nur wirklich neugierig, warum meine Argumentation falsch ist und warum die andere Option die Entscheidung war.
Charlie Parker

1
Wenn ich Zeichenfolgen vergleiche, möchte ich den Fall abflachen (falls zutreffend). Zum Beispiel würde ich verwenden: if s.upper () == 'TRUE': return True elif s.upper () == 'FALSE' return False
Bill Kidd

75

Sie können verwenden distutils.util.strtobool

>>> from distutils.util import strtobool

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

TrueWerte sind y, yes, t, true, onund 1; FalseWerte sind n, no, f, false, offund 0. Erhöht, ValueErrorwenn val etwas anderes ist.


22
Noch besser ist es bool(strtobool(my_string)), die Ausgabe als boolesche True / False-Variable
umzuwandeln

10
@AlexG verrückt, dass eine aufgerufene Funktion strtobool()tatsächlich nicht abool
dericke

61

Verwendung ast.literal_eval:

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

Warum wird flag immer in True konvertiert?

Nicht leere Zeichenfolgen sind in Python immer True.

Verwandte: Wahrheitswertprüfung


Wenn NumPy eine Option ist, dann:

>>> 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)

Es mag eine dumme Frage sein, aber warum boolkonvertiert man die Strings Trueund nicht einfach Falsein die booleschen Werte Trueund False? Scheint inkonsistentes Verhalten von dem zu sein, was inttut. Ich bin nur wirklich neugierig, warum meine Argumentation falsch ist und warum die andere Option die Entscheidung war.
Charlie Parker

2
ast.literal_eval ('false') löst eine Ausnahme aus, die meiner Meinung nach weniger wünschenswert ist
Chris

@Chris Sie können es jederzeit um try wickeln - außer in einer benutzerdefinierten Funktion, anstatt es dann direkt zu verwenden.
Ashwini Chaudhary

@HewwoCraziness Es werden nur Ausdrücke analysiert, kein zufälliger Code.
Ashwini Chaudhary

15

Die sauberste Lösung, die ich gesehen habe, ist:

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

Sicher, es erfordert einen Import, aber es hat eine ordnungsgemäße Fehlerbehandlung und erfordert sehr wenig Code, der geschrieben (und getestet) werden muss.


13

Ich empfehle dies nicht als beste Antwort, sondern nur als Alternative, aber Sie können auch Folgendes tun:

flag = reader[0] == "True"

Das Flag ist TrueID Reader [0] ist "True", andernfalls ist es False.


10

Derzeit wird ausgewertet, Trueda die Variable einen Wert hat. Hier finden Sie ein gutes Beispiel dafür, was passiert, wenn Sie beliebige Typen als Booleschen Wert auswerten.

Kurz gesagt, Sie möchten die Zeichenfolge 'True'oder isolieren 'False'und darauf ausführen eval.

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

4
@samyi Es ist gefährlich, die Eval-Methode zu verwenden. stackoverflow.com/questions/1832940/…
M07

1
Zu Ihrer Information. Dies ist eine schreckliche Idee und sollte niemals verwendet werden eval(). Meiner Meinung nach sollte es aus der Sprache entfernt werden.
Nostalg.io

Dies ist sehr schlecht, weil es eine Sicherheitslücke ist. Wenn Sie eval()Rohdaten aus einer Datei verwenden, bedeutet dies, dass jeder Benutzer mit Schreibzugriff auf diese Datei Code mit denselben Berechtigungsstufen wie Ihr Skript ausführen kann.
Keith Ripley

Außerdem, wenn Werte nicht die genaue Python Rechtschreibung haben, zum Beispiel eval('false'), eval('FALSE')wird es Fehler.
Kev

5

Sie können dict verwenden, um Zeichenfolgen in Boolesche Werte umzuwandeln. Ändern Sie diese Zeile flag = bool(reader[0])in:

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

5

Wenn Sie die Groß- und Kleinschreibung nicht berücksichtigen möchten, können Sie einfach Folgendes tun:

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

Anwendungsbeispiel:

>>> 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

3

pip installiere str2bool

>>> from str2bool import str2bool
>>> str2bool('Yes')
True
>>> str2bool('FaLsE')
False

2

Sie können mit tun json.

In [124]: import json

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

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

2

Nur um hinzuzufügen, dass, wenn Ihr Wahrheitswert variieren kann, beispielsweise wenn es sich um eine Eingabe aus verschiedenen Programmiersprachen oder aus verschiedenen Typen handelt, eine robustere Methode wäre:

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

Und eine performantere Variante wäre (Set Lookup ist O (1)):

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


0

Wenn Sie eine schnelle Möglichkeit zum Konvertieren von Zeichenfolgen in Bools benötigen (dies funktioniert bei den meisten Zeichenfolgen), versuchen Sie es.

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.