Je lis une valeur True - False
à partir d'un fichier et je dois le convertir en booléen. Actuellement, il le convertit toujours en True
même si la valeur est définie sur False
.
Voici une MWE
de ce que j'essaie de faire:
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'
Le fichier file.dat
consiste essentiellement en une seule chaîne avec la valeur True
ou False
écrite à l'intérieur. Cet arrangement semble très compliqué car il s’agit d’un exemple minimal tiré d’un code beaucoup plus volumineux et c’est ainsi que j’ai lu les paramètres.
Pourquoi flag
est-il toujours converti en True
?
bool('True')
et bool('False')
retournent toujours True
car les chaînes "True" et "False" ne sont pas vides.
Pour citer un grand homme (et Python documentation ):
5.1. Test de valeur de vérité
Tout objet peut être testé pour la valeur de vérité, pour une utilisation dans un if ou un condition ou comme opérande des opérations booléennes ci-dessous. Le les valeurs suivantes sont considérées comme fausses:
- …
- zéro de tout type numérique, par exemple,
0
,0L
,0.0
,0j
.- toute séquence vide, par exemple,
''
,()
,[]
.- …
Toutes les autres valeurs sont considérées comme vraies - donc des objets de nombreux types sont toujours vrais.
La fonction bool
intégrée utilise la procédure de test de vérité standard. C'est pourquoi vous obtenez toujours True
.
Pour convertir une chaîne en booléen, vous devez faire quelque chose comme ceci:
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
Utilisez ast.literal_eval
:
>>> import ast
>>> ast.literal_eval('True')
True
>>> ast.literal_eval('False')
False
Pourquoi flag convertit-il toujours en True?
Les chaînes non vides sont toujours vraies en Python.
Connexes: Test de valeur de vérité
Si NumPy est une option, alors:
>>> 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)
vous pouvez utiliser distutils.util.strtobool
>>> from distutils.util import strtobool
>>> strtobool('True')
1
>>> strtobool('False')
0
Les valeurs True
sont y
, yes
, t
, true
, on
et 1
; Les valeurs False
sont n
, no
, f
, false
, off
et 0
. Lève ValueError
si val est autre chose.
Je ne suggère pas cela comme la meilleure réponse, juste une alternative mais vous pouvez aussi faire quelque chose comme:
flag = reader[0] == "True"
flag sera True
id reader [0] est "True", sinon ce sera False
.
La solution la plus propre que j'ai vue est:
from distutils.util import strtobool
def string_to_bool(string):
return bool(strtobool(str(string)))
Bien sûr, il nécessite une importation, mais sa gestion des erreurs est correcte et son écriture (et son test) très réduite.
Actuellement, il est évalué à True
car la variable a une valeur. Voici un bon exemple trouvé ici de ce qui se passe lorsque vous évaluez des types arbitraires en tant que booléens.
En bref, vous voulez isoler la chaîne 'True'
ou 'False'
et exécuter eval
dessus.
>>> eval('True')
True
>>> eval('False')
False
Vous pouvez utiliser dict pour convertir une chaîne en booléen. Remplacez cette ligne flag = bool(reader[0])
par:
flag = {'True': True, 'False': False}.get(reader[0], False) # default is False
Si vous voulez être insensible à la casse, vous pouvez simplement faire:
b = True if bool_str.lower() == 'true' else False
Exemple d'utilisation:
>>> 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
Vous pouvez faire avec json
.
In [124]: import json
In [125]: json.loads('false')
Out[125]: False
In [126]: json.loads('true')
Out[126]: True
Si vous avez besoin d'un moyen rapide de convertir des chaînes en livres (cela fonctionne avec la plupart des chaînes), essayez.
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
>>> from str2bool import str2bool
>>> str2bool('Yes')
True
>>> str2bool('FaLsE')
False
Juste pour ajouter que si votre valeur de vérité peut varier, par exemple s'il s'agit d'une entrée de différents langages de programmation ou de types différents, une méthode plus robuste serait:
flag = value in ['True','true',1,'T','t','1'] # this can be as long as you want to support
Et une variante plus performante serait (la recherche d'ensemble est O (1)):
TRUTHS = set(['True','true',1,'T','t','1'])
flag = value in truths
Si vos données proviennent de JSON, vous pouvez le faire.
importer json
json.loads ('true')
Vrai