Python中将字符串转换为布尔值

1247

在Python中如何将字符串转换为布尔值?以下尝试会返回 True

>>> bool("False")
True

4
我已经创建了一个微型库,其中包括一些外语单词,例如波兰语中的“tak”,中文中的“'是的”将评估为__True__。如果不明确为true-ish,则评估为__False__。欢迎提供建议。Github链接:https://github.com/kmonsoor/str2bool - kmonsoor
但是当尝试使用 bool("string") 时,它总是返回 True...除了空字符串 bool("") - FiddleStix
你在想Perl!:-D - MikeW
39个回答

15
这是我的版本。它会检查正数和负数列表,并对未知值引发异常。而且它不接收字符串,但任何类型都可以。
def to_bool(value):
    """
       Converts 'something' to boolean. Raises exception for invalid formats
           Possible True  values: 1, True, "1", "TRue", "yes", "y", "t"
           Possible False values: 0, False, None, [], {}, "", "0", "faLse", "no", "n", "f", 0.0, ...
    """
    if str(value).lower() in ("yes", "y", "true",  "t", "1"): return True
    if str(value).lower() in ("no",  "n", "false", "f", "0", "0.0", "", "none", "[]", "{}"): return False
    raise Exception('Invalid value for boolean conversion: ' + str(value))

样例运行结果:

>>> to_bool(True)
True
>>> to_bool("tRUe")
True
>>> to_bool("1")
True
>>> to_bool(1)
True
>>> to_bool(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in to_bool
Exception: Invalid value for boolean conversion: 2
>>> to_bool([])
False
>>> to_bool({})
False
>>> to_bool(None)
False
>>> to_bool("Wasssaaaaa")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in to_bool
Exception: Invalid value for boolean conversion: Wasssaaaaa
>>>

有时候会遇到这种情况:to_bool(["hello"]),如果支持[]的话,这应该是一个完全有效的调用。 - Rafael T
1
返回值为“异常:布尔转换无效的值:['hello']”,这是预期的且有记录的。在我看来,一个空列表显然是假的,但 ['false'] 不清楚到底是什么,所以我有意将其省略——这是一种特性而不是错误。如果您想要支持将非空列表返回为 true 的话,那将很容易添加。 - Petrucio
1
确保你已经记录了它。但在现实生活中,人们永远不会调用 to_bool([])。相反,他会做类似这样的事情:myList = someFunctionThatReturnAList `if (is_bool(myList)):...´所以如果有一个列表并想知道这个列表是否为None或为空,则可以这样做。 - Rafael T
为什么不试试这个:
def a2b(arg): ... default = bool(arg) ... if isinstance(arg, str): ... return arg.lower() in ['true', 't', 'yes', 'y', '1'] ... else: ... return default
- ThePracticalOne
5
建议优先使用值错误,而不是普通异常。 - dshepherd
实际上,我觉得他们更可能执行if my_list:而不是if to_bool(my_list):。 我倾向于认为尝试支持listdict可能是个坏主意。 除非我已经知道它是空的,否则我无法利用该支持,因为一个非空的会抛出错误,但是如果我已经知道了这一点,我甚至不需要这个功能。 其他的不对称性也有点靠不住。 字符串“'NONE'”被转换为False(与正常的Python不一致),支持float 0.0也具有与list / dict相同的问题。 - jpmc26

13

一个很酷的、简单的技巧(基于@Alan Marchiori发布的),但使用yaml:

import yaml

parsed = yaml.load("true")
print bool(parsed)

如果这太宽了,可以通过测试类型结果进行细化。 如果yaml返回的类型是字符串,则无法转换为任何其他类型(至少我能想到的),因此您可以单独处理它,或者让它保持不变。

我不会猜测速度,但既然我已经在Qt gui下使用yaml数据了,那么这就有了一个很好的对称性。


2
yaml 模块是一个第三方库:PyYAML - Peter Wood
1
为了更好地防范不受信任的输入,建议使用yaml.safe_load而非yaml.load - dreftymac
这个很好,因为它也可以处理 - Laurenz

10

字典(实际上是defaultdict)可以为您提供一种非常简单的方法来完成此技巧:

from collections import defaultdict
bool_mapping = defaultdict(bool) # Will give you False for non-found values
for val in ['True', 'yes', ...]:
    bool_mapping[val] = True

print(bool_mapping['True']) # True
print(bool_mapping['kitten']) # False

如果您只想映射已知的值并在其他情况下抛出异常:

truthy_strings = ['True', 'yes']  # ... and so on
falsy_strings = ['False', 'no']   # ... and so on

bool_mapping = {}
for v in truthy_strings:
    bool_mapping[v] = True
for v in falsy_strings:
    bool_mapping[v] = False

如果你想聪明过头,可以使用 itertools 来缩短代码。

from itertools import chain, repeat

bool_mapping = dict(chain(zip(truthy_strings, repeat(True)), zip(falsy_strings, repeat(False))))

这可能很蠢,但itertools技巧有点有趣。


9

我不同意这里的任何解决方法,因为它们太过宽松。当解析字符串时,这通常不是您想要的。

因此,这是我使用的解决方案:

def to_bool(bool_str):
    """Parse the string and return the boolean value encoded or raise an exception"""
    if isinstance(bool_str, basestring) and bool_str: 
        if bool_str.lower() in ['true', 't', '1']: return True
        elif bool_str.lower() in ['false', 'f', '0']: return False

    #if here we couldn't parse it
    raise ValueError("%s is no recognized as a boolean value" % bool_str)

结果如下:

>>> [to_bool(v) for v in ['true','t','1','F','FALSE','0']]
[True, True, True, False, False, False]
>>> to_bool("")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in to_bool
ValueError: '' is no recognized as a boolean value

为了明确一下,因为看起来我的回答似乎冒犯了某个人:

关键是你不想只测试一个值并假设另一个值。我认为你并不总是想将所有东西都映射到未解析的值。那样会产生容易出错的代码。

所以,如果你知道你想要什么,就把它编码进去。


3
我认为你没有抓住重点:答案的重点是展示普遍原则,而不是告诉提问者应该如何做。最初提问的人过于纠结一个其实很简单的问题。 - Keith Gaughan
9
@Keith 我不同意。关键是要按照所提出的问题来回答。 - estani
2
所问问题是如何将字符串转换为布尔值。这就是我回答的问题。我不知道原帖中哪些被认为是有效的布尔值字符串,你也不知道。因此,更重要的是展示通用原则,而不是给予完整答案。原帖作者并不需要所有东西都被详细解释:他们只需要演示通用原则。从那开始,任何有能力的人都会得出您的答案。 - Keith Gaughan
3
@dshepherd,isinstance的作用是确保我正在解析我期望的内容。我正在解析字符串,因此如果方法car_race.lower()偶然返回'1',它不应该返回true,而应该引发ValueError。但在其他情况下可能已经足够了。 - estani
2
@CivFan 有趣的观点。虽然我尝试过,但它读起来不太好(对我来说)。elif由于return关键字是多余的,但它可以为您提供更多信息,而无需扫描return。但这只是我的看法,如果存在PEP样式违规,我会进行更改。在没有其他限制的情况下,我们应该始终注重可读性(并且标准也是如此)。感谢您的提示和有趣的评论! - estani
显示剩余3条评论

8

通过以下简单的逻辑,您可以将一个字符串(例如a = 'true''false')转换为布尔值。

a = a.lower() == 'true'

如果 a == 'true',那么这将设置 a=True;如果 a == 'false',那么这将设置 a=False

如果a = '0'呢? - sagi
@sagi - 然后我们可以使用: a = (str(a).lower() == 'true') | (str(a).lower() == '1') - Sagar Deshmukh
但这也会将"truee"转换为true。通常,如果输入无效,我们希望抛出异常。 - Neuron

6
另一个选项
from ansible.module_utils.parsing.convert_bool import boolean
boolean('no')
# False
boolean('yEs')
# True
boolean('true')
# True

6

我使用

# function
def to_bool(x):
    return x in ("True", "true", True)

# test cases
[[x, to_bool(x)] for x in [True, "True", "true", False, "False", "false", None, 1, 0, -1, 123]]
"""
Result:
[[True, True],
 ['True', True],
 ['true', True],
 [False, False],
 ['False', False],
 ['false', False],
 [None, False],
 [1, True],
 [0, False],
 [-1, False],
 [123, False]]
"""

5

你可能已经有了解决方案,但对于那些想要使用“标准”假值(包括None、[]、{}和"")以及false、no和0来将值转换为布尔值的人,以下是一种方法。

def toBoolean( val ):
    """ 
    Get the boolean value of the provided input.

        If the value is a boolean return the value.
        Otherwise check to see if the value is in 
        ["false", "f", "no", "n", "none", "0", "[]", "{}", "" ]
        and returns True if value is not in the list
    """

    if val is True or val is False:
        return val

    falseItems = ["false", "f", "no", "n", "none", "0", "[]", "{}", "" ]

    return not str( val ).strip().lower() in falseItems

1
最好使用集合,而不是“not in”,您选择的错误项有些特殊。 - SilentGhost

5
如果您可以控制返回true/false的实体,一种选项是让它返回1/0而不是true/false,然后: boolean_response = bool(int(response)) 额外的int转换处理来自网络的响应,这些响应始终为字符串。
2021年更新:“始终为字符串”这是一个天真的观察。这取决于库使用的序列化协议。大多数Web开发人员使用的高级库的默认序列化通常是在序列化为字节之前将其转换为字符串。然后,在另一侧,它从字节到字符串进行反序列化,因此您已经丢失了任何类型信息。

5

如果您知道输入要么是"True",要么是其他内容,那么为什么不使用以下代码:

def bool_convert(s):
    return s == "True"

你实际上不需要 if s else False 这一部分。想想 "False" == "True" 已经会返回 False 了。 - Taylor D. Edmiston
如果您不确定输入的 s 是字符串还是布尔值,可以添加 if type(s) is bool: return s - kontur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接