【问题标题】:Convert True/False value read from file to boolean将从文件读取的 True/False 值转换为布尔值
【发布时间】:2014-03-11 00:37:15
【问题描述】:

我正在从文件中读取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 文件基本上由一个字符串组成,其中写入值TrueFalse。这种安排看起来非常复杂,因为这是来自更大代码的最小示例,这就是我将参数读入其中的方式。

为什么flag 总是转换为True

【问题讨论】:

标签: python string boolean


【解决方案1】:

bool('True')bool('False') 总是返回 True,因为字符串 'True' 和 'False' 不为空。

引用一位伟人(和 Python documentation):

5.1. Truth Value Testing

可以测试任何对象的真值,用于 if 或 while 条件或作为以下布尔运算的操作数。这 以下值被认为是错误的:

  • 任何数字类型的零,例如,00L0.00j
  • 任何空序列,例如,''()[]

所有其他值都被认为是真实的——所以许多类型的对象 总是正确的。

内置的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

【讨论】:

  • 你可以通过 raise ValueError("Cannot covert {} to a bool".format(s)) 让它成为一个“英雄”ValueError
  • 选择这个是因为它不使用额外的包。谢谢大家!
  • “额外包”有什么问题?你指的是ast吗?它是标准库的一部分,因此并不是额外的。
  • 这可能是一个愚蠢的问题,但为什么bool 只是不将字符串TrueFalse 转换为布尔值TrueFalse?似乎与int 的行为不一致。我真的很好奇为什么我的推理是错误的,为什么另一个选择是决定。
  • 每当比较字符串时,我都喜欢使大小写变平(如果适用)。例如我会使用: if s.upper() == 'TRUE': return True elif s.upper() == 'FALSE' return False
【解决方案2】:

你可以使用distutils.util.strtobool

>>> from distutils.util import strtobool

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

True 的值为yyesttrueon1False 的值为 nnoffalseoff0。如果 val 是其他值,则引发 ValueError

【讨论】:

  • 更好的是,bool(strtobool(my_string)) 将输出转换为布尔 True / False 变量
  • @AlexG 疯了,一个名为strtobool() 的函数实际上并没有返回bool
【解决方案3】:

使用ast.literal_eval:

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

为什么flag总是转换为True?

非空字符串在 Python 中始终为 True。

相关:Truth Value Testing


如果 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 只是不将字符串TrueFalse 转换为布尔值TrueFalse?似乎与int 的行为不一致。我真的很好奇为什么我的推理是错误的,为什么另一个选择是决定。
  • ast.literal_eval('false') 抛出异常,我认为这使得它不太理想
  • @Chris 你总是可以将它包裹在自定义函数中的 try-except 中,而不是直接使用它。
  • @HewwoCraziness 它只解析表达式而不是任何随机代码。
【解决方案4】:

我见过的最干净的解决方案是:

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

当然,它需要导入,但它具有适当的错误处理,并且只需要编写(和测试)很少的代码。

【讨论】:

  • 这不起作用,除非输入值实际上可以是布尔值,否则,它似乎会抛出一个值错误。我唯一能想到的就是在你的函数中添加一个 try/except 并在 ValueError 上返回 false。
【解决方案5】:

我不建议将此作为最佳答案,只是一个替代方案,但您也可以执行以下操作:

flag = reader[0] == "True"

标志将为True id reader[0] 为“True”,否则为False

【讨论】:

    【解决方案6】:

    目前,它正在评估为True,因为该变量有一个值。 good example found here 说明当您将任意类型评估为布尔值时会发生什么。

    简而言之,您要做的是隔离'True''False' 字符串并在其上运行eval

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

    【讨论】:

    • @samyi 使用 eval 方法很危险。 stackoverflow.com/questions/1832940/…
    • 仅供参考。这是一个糟糕的主意,您应该永远使用eval()。在我看来,它应该从语言中删除。
    • 这是非常非常糟糕的,因为它是一个安全漏洞。如果您对文件中的原始数据使用eval(),则意味着任何对该文件具有写入权限的人都可以执行与您的脚本具有相同权限级别的代码。
    • 另外,如果值没有准确的 python 拼写,例如eval('false'), eval('FALSE') 会出错。
    【解决方案7】:

    如果你想不区分大小写,你可以这样做:

    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
    

    【讨论】:

      【解决方案8】:

      您可以使用 dict 将字符串转换为布尔值。将此行 flag = bool(reader[0]) 更改为:

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

      【讨论】:

        【解决方案9】:

        点安装str2bool

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

        【讨论】:

          【解决方案10】:

          您可以使用json

          In [124]: import json
          
          In [125]: json.loads('false')
          Out[125]: False
          
          In [126]: json.loads('true')
          Out[126]: True
          

          【讨论】:

          • 当字符串为“真”或“假”(即标题格式)时,会出现 JSON 解码错误。在这种情况下使用 json.loads('False'.lower)。
          【解决方案11】:

          只是补充一点,如果你的真值可以变化,例如,如果它是来自不同编程语言或不同类型的输入,那么更健壮的方法是:

          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
          

          【讨论】:

            【解决方案12】:

            如果你的数据来自json,你可以这样做

            导入 json

            json.loads('true')

            是的

            【讨论】:

              【解决方案13】:

              如果您需要快速将字符串转换为布尔值(大多数字符串的函数)的方法,请尝试。

              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
              
              

              【讨论】:

                【解决方案14】:

                使用dicts将“True”转换为True:

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

                【讨论】:

                  【解决方案15】:

                  如果你有

                  >>> my_value = "False"
                  

                  然后要么做

                  >>> my_value in "False"
                  True
                  >>> my_value in "True"
                  False
                  

                  >>> "False" in my_value
                  True
                  >>> "True" in my_value
                  False
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-04-27
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-12-28
                    • 2015-09-18
                    • 1970-01-01
                    相关资源
                    最近更新 更多