แปลงค่า True / False ที่อ่านจากไฟล์เป็นบูลีน


88

ฉันกำลังอ่าน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

คำตอบ:


101

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

24
คุณสามารถทำให้มันเป็น "วีรบุรุษ" ด้วยการทำValueError raise ValueError("Cannot covert {} to a bool".format(s))
SethMMorton

เลือกอันนี้เนื่องจากไม่ใช้แพ็คเกจเสริม ขอบคุณเพื่อน!
Gabriel

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

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เป็นอย่างอื่น


23
ยิ่งไปกว่านั้นคือทำbool(strtobool(my_string))เอาต์พุตเป็นตัวแปรบูลีน True / False
AlexG

11
@AlexG บ้าที่ฟังก์ชั่นที่เรียกstrtobool()ไม่ได้ในความเป็นจริงกลับ abool
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

@Chris คุณสามารถใช้ลองได้ทุกเมื่อยกเว้นในฟังก์ชันที่กำหนดเองแทนที่จะใช้โดยตรง
Ashwini Chaudhary

@HewwoCraziness มันแยกเฉพาะนิพจน์ไม่ใช่โค้ดสุ่มใด ๆ
Ashwini Chaudhary

16

วิธีแก้ปัญหาที่สะอาดที่สุดที่ฉันเคยเห็นคือ:

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

แน่นอนว่าต้องมีการนำเข้า แต่มีการจัดการข้อผิดพลาดที่เหมาะสมและต้องเขียนโค้ดน้อยมาก (และทดสอบ)


วิธีนี้ใช้ไม่ได้เว้นแต่ว่าค่าที่ป้อนจะเป็นบูลีนไม่เช่นนั้นดูเหมือนว่าจะทำให้เกิดข้อผิดพลาดค่า สิ่งเดียวที่ฉันคิดได้คือเพิ่ม try / except ให้กับฟังก์ชันของคุณและValueErrorกลับเป็นเท็จ
อารีย์

13

ฉันไม่ได้แนะนำว่านี่เป็นคำตอบที่ดีที่สุดเป็นเพียงทางเลือกอื่น แต่คุณสามารถทำสิ่งต่างๆเช่น:

flag = reader[0] == "True"

ธงจะTrueอ่านรหัส [0] คือ "ทรู" 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()ข้อมูลดิบจากไฟล์หมายความว่าทุกคนที่มีสิทธิ์เขียนไฟล์นั้นสามารถเรียกใช้โค้ดในระดับสิทธิ์เดียวกับสคริปต์ของคุณได้
Keith Ripley

นอกจากนี้หากค่าไม่ได้สะกดหลามแน่นอนเช่น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

หากต้องการเพิ่มว่าหากค่าความจริงของคุณอาจแตกต่างกันไปตัวอย่างเช่นหากเป็นการป้อนข้อมูลจากภาษาโปรแกรมที่แตกต่างกันหรือจากประเภทต่างๆวิธีที่มีประสิทธิภาพมากขึ้นคือ:

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

หากคุณต้องการวิธีที่รวดเร็วในการแปลงสตริงเป็นบูล (ฟังก์ชันที่มีสตริงส่วนใหญ่) ให้ลอง

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.