Ubah nilai True / False dibaca dari file ke boolean

88

Saya membaca True - Falsenilai dari file dan saya perlu mengubahnya menjadi boolean. Saat ini selalu mengubahnya menjadi Truemeskipun nilainya disetel ke False.

Inilah MWEyang saya coba lakukan:

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'

The file.datberkas pada dasarnya terdiri dari satu string dengan nilai Trueatau Falsedalam tertulis. Susunannya terlihat sangat berbelit-belit karena ini adalah contoh minimal dari kode yang jauh lebih besar dan begitulah cara saya membaca parameter di dalamnya.

Mengapa flagselalu beralih ke True?

Gabriel
sumber
1
pip install str2bool
Symon

Jawaban:

101

bool('True')dan bool('False')selalu kembali Truekarena string 'True' dan 'False' tidak kosong.

Mengutip orang hebat (dan dokumentasi Python ):

5.1. Pengujian Nilai Kebenaran

Objek apa pun dapat diuji untuk nilai kebenaran, untuk digunakan dalam kondisi if atau while atau sebagai operan operasi Boolean di bawah ini. Nilai berikut dianggap salah:

  • nol dari setiap tipe numerik, misalnya, 0, 0L, 0.0, 0j.
  • setiap urutan kosong, misalnya, '', (), [].

Semua nilai lain dianggap benar - jadi objek dari berbagai jenis selalu benar.

Fungsi built-in boolmenggunakan prosedur pengujian kebenaran standar. Itulah mengapa Anda selalu mendapatkannya True.

Untuk mengonversi string menjadi boolean, Anda perlu melakukan sesuatu seperti ini:

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
Nigel Tufnel
sumber
23
Anda bisa menjadikannya "heroik" ValueErrordengan melakukan raise ValueError("Cannot covert {} to a bool".format(s)).
SethMMorton
Memilih yang ini karena tidak menggunakan paket tambahan. Terima kasih teman-teman!
Gabriel
1
Apa yang salah dengan "paket ekstra"? Apakah yang Anda maksud ast? Ini adalah bagian dari pustaka standar, jadi tidak terlalu ekstra.
SethMMorton
4
Ini mungkin pertanyaan yang konyol tapi mengapa booltidak mengubah string Truedan Falseke nilai boolean Truedan False? Tampaknya perilaku tidak konsisten dari apa yang intdilakukannya. Saya hanya benar-benar ingin tahu mengapa alasan saya salah dan mengapa pilihan lain adalah keputusan.
Charlie Parker
1
Setiap kali membandingkan string, saya ingin meratakan casing, (jika memungkinkan). misalnya saya akan menggunakan: if s.upper () == 'TRUE': return True elif s.upper () == 'FALSE' return False
Bill Kidd
75

Kamu dapat memakai distutils.util.strtobool

>>> from distutils.util import strtobool

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

Truenilai-nilai y, yes, t, true, ondan 1; Falsenilai-nilai n, no, f, false, offdan 0. Meningkat ValueErrorjika val adalah yang lain.

Francesco Nazzaro
sumber
23
Lebih baik lagi, lakukan bool(strtobool(my_string))untuk mentransmisikan output sebagai variabel True / False boolean
AlexG
11
@AlexG gila bahwa fungsi yang dipanggil strtobool()tidak, pada kenyataannya, mengembalikan abool
dericke
61

Penggunaan ast.literal_eval:

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

Mengapa bendera selalu dikonversi ke True?

String yang tidak kosong selalu True dalam Python.

Terkait: Pengujian Nilai Kebenaran


Jika NumPy adalah opsi, maka:

>>> 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)
Ashwini Chaudhary
sumber
Ini mungkin pertanyaan yang konyol tapi mengapa booltidak mengubah string Truedan Falseke nilai boolean Truedan False? Tampaknya perilaku tidak konsisten dari apa yang intdilakukannya. Saya hanya benar-benar ingin tahu mengapa alasan saya salah dan mengapa pilihan lain adalah keputusan.
Charlie Parker
2
ast.literal_eval ('false') memberikan pengecualian, yang menurut saya membuatnya kurang diminati
Chris
@Chris Anda selalu dapat menggabungkannya dengan try-kecuali dalam fungsi kustom alih-alih menggunakannya secara langsung.
Ashwini Chaudhary
@HewwoCraziness Ini hanya mengurai ekspresi, bukan kode acak.
Ashwini Chaudhary
16

Solusi terbersih yang pernah saya lihat adalah:

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

Tentu, ini membutuhkan impor, tetapi memiliki penanganan kesalahan yang tepat dan hanya membutuhkan sedikit kode untuk ditulis (dan diuji).

vpetersson.dll
sumber
Ini tidak berfungsi kecuali jika nilai input benar-benar dapat berupa boolean, jika tidak, tampaknya akan memunculkan kesalahan nilai. Satu-satunya hal yang dapat saya pikirkan adalah menambahkan percobaan / kecuali ke fungsi Anda dan ValueErrormengembalikan false.
Ari
13

Saya tidak menyarankan ini sebagai jawaban terbaik, hanya alternatif tetapi Anda juga dapat melakukan sesuatu seperti:

flag = reader[0] == "True"

bendera akan menjadi Truepembaca id [0] adalah "Benar", jika tidak maka akan demikian False.

elParaguayo
sumber
10

Saat ini, itu sedang mengevaluasi Truekarena variabel memiliki nilai. Ada contoh bagus yang ditemukan di sini tentang apa yang terjadi saat Anda mengevaluasi jenis arbitrer sebagai boolean.

Singkatnya, yang ingin Anda lakukan adalah mengisolasi string 'True'atau 'False'dan menjalankannya eval.

>>> eval('True')
True
>>> eval('False')
False
Gautam Joshi
sumber
4
@samyi Berbahaya menggunakan metode eval. stackoverflow.com/questions/1832940/…
M07
1
FYI. Ini adalah ide yang buruk dan Anda tidak boleh menggunakannya eval(). Menurut saya, itu harus dihapus dari bahasa.
Nostalg.io
Ini SANGAT SANGAT BURUK karena ini adalah kelemahan keamanan. Jika Anda menggunakan eval()data mentah dari sebuah file, itu berarti siapa pun yang memiliki akses tulis ke file tersebut dapat mengeksekusi kode pada tingkat izin yang sama dengan skrip Anda.
Keith Ripley
Selain itu, jika nilai tidak memiliki ejaan python yang tepat, misalnya eval('false'), eval('FALSE')kesalahan akan terjadi.
kev
5

Anda dapat menggunakan dict untuk mengonversi string menjadi boolean. Ubah baris ini flag = bool(reader[0])menjadi:

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

Jika Anda ingin peka huruf besar / kecil, Anda dapat melakukan:

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

Contoh penggunaan:

>>> 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
caleb
sumber
3

pip instal str2bool

>>> from str2bool import str2bool
>>> str2bool('Yes')
True
>>> str2bool('FaLsE')
False
Symon
sumber
2

Anda bisa melakukannya dengan json.

In [124]: import json

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

In [126]: json.loads('true')
Out[126]: True
Rahul KP
sumber
2

Hanya untuk menambahkan bahwa jika nilai kebenaran Anda dapat bervariasi, misalnya jika itu adalah masukan dari bahasa pemrograman yang berbeda atau dari jenis yang berbeda, metode yang lebih kuat adalah:

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

Dan varian yang lebih berkinerja adalah (set lookup is O (1)):

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

Jika data Anda dari json, Anda dapat melakukannya

import json

json.loads ('true')

Benar

Ivan Camilito Ramirez Verdes
sumber
0

Jika Anda membutuhkan cara cepat untuk mengubah string menjadi bools (yang berfungsi dengan sebagian besar string) coba.

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

pengguna6830669
sumber
0

Menggunakan dicts untuk mengubah "True" menjadi True:

def str_to_bool(s: str):
    status = {"True": True,
                "False": False}
    try:
        return status[s]
    except KeyError as e:
        #logging
chris
sumber