Dosyadan okunan Doğru / Yanlış değerini mantıksal değere dönüştür


88

True - FalseBir dosyadan bir değer okuyorum ve onu boolean'a dönüştürmem gerekiyor. Şu anda True, değer olarak ayarlanmış olsa bile her zaman dönüştürür False.

İşte MWEyapmaya çalıştığım şeylerden bazıları:

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.datDosya temelde değeri olan tek bir dize oluşur Trueveya Falseyazılı içerden. Düzenleme çok kıvrımlı görünüyor çünkü bu çok daha büyük bir koddan alınan minimal bir örnek ve parametreleri bu şekilde okudum.

Neden her flagzaman dönüştürülüyor True?


1
pip install str2bool
Symon

Yanıtlar:


101

bool('True')ve bool('False')her zaman geri döner Trueçünkü 'True' ve 'False' dizeleri boş değildir.

Harika bir adama (ve Python belgelerine ) alıntı yapmak gerekirse :

5.1. Gerçek Değer Testi

Herhangi bir nesne, bir if veya while koşulunda kullanım için veya aşağıdaki Boolean işlemlerinin işleneni olarak doğruluk değeri için test edilebilir. Aşağıdaki değerler yanlış kabul edilir:

  • herhangi bir sayısal tür sıfır, örneğin 0, 0L, 0.0, 0j.
  • boş bir sıra, örneğin, '', (), [].

Diğer tüm değerler doğru kabul edilir - bu nedenle birçok türde nesneler her zaman doğrudur.

Yerleşik boolişlev, standart doğruluk testi prosedürünü kullanır. Bu yüzden her zaman anlıyorsun True.

Bir dizeyi boolean'a dönüştürmek için şuna benzer bir şey yapmanız gerekir:

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

24
ValueErrorYaparak bunu bir "kahramanca" yapabilirsiniz raise ValueError("Cannot covert {} to a bool".format(s)).
SethMMorton

Ekstra paket kullanmadığı için bunu seçmek. Teşekkürler beyler!
Gabriel

1
"Ekstra paketlerin" nesi var? Kastediyor musunuz ast? Standart kütüphanenin bir parçası, bu yüzden gerçekten ekstra değil.
SethMMorton

4
aptalca bir soru olabilir ama neden booldizeleri Trueve Falseboole değerlerine Trueve False? Yaptığına göre tutarsız bir davranış gibi görünüyor int. Mantığımın neden yanlış olduğunu ve neden diğer seçeneğin karar olduğunu gerçekten merak ediyorum.
Charlie Parker

1
Dizeleri ne zaman karşılaştırdığımda, durumu düzleştirmeyi seviyorum (uygun olan yerlerde). örneğin şunu kullanırdım: eğer s.upper () == 'DOĞRU': döndür True elif s.upper () == 'YANLIŞ' return False
Bill Kidd

75

kullanabilirsiniz distutils.util.strtobool

>>> from distutils.util import strtobool

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

Truedeğerleri y, yes, t, true, onve 1; Falsedeğerlerdir n, no, f, false, offve 0. Artırdı ValueErroreğer val başka bir şey değildir.


23
Daha da iyisi, bool(strtobool(my_string))çıktıyı mantıksal bir Doğru / Yanlış değişkeni olarak kullanmak
AlexG

11
@AlexG crazy, çağrılan bir işlev strtobool()aslında birbool
dericke döndürmez

61

Kullanım ast.literal_eval:

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

Bayrak neden her zaman True'ya dönüşür?

Boş olmayan dizeler Python'da her zaman True'dur.

İlgili: Gerçek Değer Testi


NumPy bir seçenekse, o zaman:

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

aptalca bir soru olabilir ama neden booldizeleri Trueve Falseboole değerlerine Trueve False? Yaptığına göre tutarsız bir davranış gibi görünüyor int. Mantığımın neden yanlış olduğunu ve neden diğer seçeneğin karar olduğunu gerçekten merak ediyorum.
Charlie Parker

2
ast.literal_eval ('false') bir istisna atıyor ve bence bunu daha az arzu edilir kılıyor
Chris

@Chris Doğrudan kullanmak yerine özel bir işlev haricinde her zaman Try etrafına sarabilirsiniz.
Ashwini Chaudhary

@HewwoCraziness Herhangi bir rastgele kodu değil sadece ifadeleri ayrıştırır.
Ashwini Chaudhary

16

Gördüğüm en temiz çözüm:

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

Elbette, bir içe aktarma gerektirir, ancak uygun hata işlemeye sahiptir ve çok az kod yazılmasını (ve test edilmesini) gerektirir.


Girdi değeri gerçekte bir boole olmadığı sürece bu işe yaramaz, aksi takdirde bir değer hatası veriyor gibi görünür. Aklıma gelen tek şey, işlevinize bir denemek / eklemek ve ValueErrordönüşte yanlış.
Ari

13

Bunu en iyi cevap olarak önermiyorum, sadece bir alternatif ama aynı zamanda şöyle bir şey de yapabilirsiniz:

flag = reader[0] == "True"

bayrak Truekimlik okuyucu olacak [0] "Doğru", aksi takdirde geçerli olacaktır False.


10

Şu anda, Truedeğişkenin bir değeri olduğu için değerlendiriliyor . Burada bulunan iyi bir örnek var , bir boolean olarak keyfi türlerini değerlendirmek ne olur.

Kısacası, yapmak istediğiniz şey 'True'veya 'False'dizesini izole etmek ve evalüzerinde çalıştırmaktır .

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

4
@samyi eval yöntemini kullanmak tehlikelidir. stackoverflow.com/questions/1832940/…
M07

1
FYI. Bu berbat bir fikir ve asla kullanmamalısın eval(). Bence dilden kaldırılması gerekiyor.
Nostalg.io

Bu ÇOK ÇOK KÖTÜ çünkü bir güvenlik açığı. eval()Bir dosyadaki ham verilerde kullanırsanız , bu, o dosyaya yazma erişimi olan herkesin komut dosyanızla aynı izin düzeyinde kod yürütebileceği anlamına gelir.
Keith Ripley

Değerler örneğin değil tam piton yazım varsa, ayrıca eval('false'), eval('FALSE')bu hata olur.
kev

5

Dict'i boolean'a çevirmek için kullanabilirsiniz. Bu satırı şu flag = bool(reader[0])şekilde değiştirin :

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

5

Büyük / küçük harfe duyarlı olmak istiyorsanız, şunları yapabilirsiniz:

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

Örnek kullanım:

>>> 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 str2bool yüklemek

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

2

İle yapabilirsin json.

In [124]: import json

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

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

2

Doğruluk değeriniz değişebiliyorsa, örneğin farklı programlama dillerinden veya farklı türlerden bir girdiyse, daha sağlam bir yöntem şöyle olacaktır:

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

Ve daha performanslı bir varyant şöyle olacaktır (set araması O (1)):

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


0

Dizeleri boollere dönüştürmenin hızlı bir yoluna ihtiyacınız varsa (bu, çoğu dizeyle çalışır) deneyin.

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

"Doğru" yu True olarak dönüştürmek için dicts kullanma:

def str_to_bool(s: str):
    status = {"True": True,
                "False": False}
    try:
        return status[s]
    except KeyError as e:
        #logging
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.