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个回答

1309

实际上,您只需将字符串与您期望接受为表示true的内容进行比较,因此您可以这样做:

s == 'True'

或者检查一堆值:

s.lower() in ['true', '1', 't', 'y', 'yes', 'yeah', 'yup', 'certainly', 'uh-huh']

使用以下内容时请小心:

>>> bool("foo")
True
>>> bool("")
False

空字符串被解释为 False,但其他所有内容都被解释为 True。因此,它不适用于任何解析目的。


69
s == "True"这个表达式非常简单。但是我曾经看到有些人在这方面搞砸了。下面是一个将字符串转换为布尔值的函数,它保证了正确性:def convert(s): if s == "True": return True; return False. - S.Lott
42
我更喜欢使用"return s == "True"",而不是if/else结构。 - Dana
41
如果s等于"True",则返回真(True),如果s等于"False",则返回假(False),否则引发异常。 - Unknown
19
将字符串解析为布尔值的功能已经在distutils.util.strtobool中实现: https://dev59.com/snRB5IYBdhLWcg3wHkPi#18472142 - jzwiener
39
我知道这个话题非常旧了,但我想证明我刚刚花了4个小时尝试调试我的代码。我的错误在于尝试将 bool("False") 进行强制类型转换。它总是会被转换为 True - Ev.
显示剩余30条评论

545

警告: 此答案在Python 3.12中将不再运行(自3.10起已弃用)

使用:

bool(distutils.util.strtobool(some_string))

真值包括 y、yes、t、true、on 和 1;假值包括 n、no、f、false、off 和 0。如果 val 是其他值,则会引发 ValueError。

请注意,distutils.util.strtobool() 返回整数表示形式,因此需要使用 bool() 进行包装以获取布尔值。

鉴于distutils将不再是标准库的一部分,这里提供了distutils.util.strtobool()的代码(请参见3.11.2的源代码)。

def strtobool (val):
    """Convert a string representation of truth to true (1) or false (0).
    True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
    are 'n', 'no', 'f', 'false', 'off', and '0'.  Raises ValueError if
    'val' is anything else.
    """
    val = val.lower()
    if val in ('y', 'yes', 't', 'true', 'on', '1'):
        return 1
    elif val in ('n', 'no', 'f', 'false', 'off', '0'):
        return 0
    else:
        raise ValueError("invalid truth value %r" % (val,))

6
那个函数很诱人。如果它能处理整数、Nonestr(None)作为输入,那就完美了。 - MarkHu
30
我更喜欢这个答案,即从stdlib中获取并且完全符合所需功能。通常情况下,如果你没有像 if x == False 这样的不好的操作,就没有必要使用实际的布尔值而不是 1/0。如果你正在处理整数和 None,则不需要特殊函数,只需直接检查它们,如 if myint:if not maybe_none_var: - Anentropic
6
@Secator boolint 的一个子类。 - Anentropic
25
为了方便大家避免在Google上搜索错误:为使此操作生效,请导入distutils和import distutils.util。 - Edward B.
17
请注意,自 Python 3.10 起,distutils 包已被弃用,并将在版本 3.12 中移除。 - jan-di
显示剩余7条评论

358
def str2bool(v):
  return v.lower() in ("yes", "true", "t", "1")

那么就这样调用它:
>>> str2bool("yes")
True
>>> str2bool("no")
False
>>> str2bool("stuff")
False
>>> str2bool("1")
True
>>> str2bool("0")
False

明确处理真和假:

你也可以让你的函数明确地检查一个真单词列表和一个假单词列表。如果它既不在真单词列表中,也不在假单词列表中,那么你可以抛出一个异常。


50
可以使用 str(v).lower() 替代 v.lower() 进行小幅改进。这样,即使输入不是字符串(例如1、0),也可以正常运行。请注意,不要改变原意。 - kmonsoor
回复:要明确处理 true/false,您还可以在字符串不匹配时提供默认值,就像 true/false 命令行提示的工作方式一样: 继续吗?(y/N) - Johnus
如果你打算包括“t”,可能要加上“y”... - undefined

190

JSON解析器还可以将字符串转换为Python中合理的类型,这在一般情况下同样很有用。

>>> import json
>>> json.loads("false".lower())
False
>>> json.loads("True".lower())
True

3
不过要小心,没有验证返回类型是否为布尔值。 json.loads("[42]".lower()) -> [42] - selle
为什么需要使用.lower()?当我不使用它时,例如 x = "False" j = json.loads(x),我会收到错误消息 json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) - Ambassador Kosh
@AmbassadorKosh 因为 JSON 只能识别字面上的 truefalse 值;请参阅 https://json-schema.org/understanding-json-schema/reference/boolean.html。 - Luis
这个就像魔法一样好用!非常感谢。 - Orkhan Shirin

130
Python 2.6 开始,您可以使用 ast.literal_eval,并且它仍然可在 Python 3 中使用。
评估表达式节点或仅包含Python字面值或容器显示的字符串。提供的字符串或节点只能由以下Python字面结构组成:字符串、字节、数字、元组、列表、字典、集合、布尔值、NoneEllipsis
这可用于评估包含Python值的字符串,而无需解析这些值。它不能评估任意复杂的表达式,例如涉及运算符或索引的表达式。
过去曾将此函数记录为“安全”,但没有定义其含义,这是误导性的。与更通用的eval()不同,它专门设计为不执行Python代码。没有命名空间、名称查找或调用能力。但是,它并不是免受攻击的:相对较小的输入可能会导致内存耗尽或C堆栈耗尽,从而使进程崩溃。某些输入还可能导致过度CPU消耗拒绝服务。因此,不建议在不受信任的数据上调用它
只要您确定您的字符串将是"True""False",这似乎可以工作:
>>> ast.literal_eval("True")
True
>>> ast.literal_eval("False")
False
>>> ast.literal_eval("F")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 68, in literal_eval
    return _convert(node_or_string)
  File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 67, in _convert
    raise ValueError('malformed string')
ValueError: malformed string
>>> ast.literal_eval("'False'")
'False'

我通常不会推荐这样做,但它是完全内置的,根据您的需求可能是合适的选择。


2
不确定这个解决方案的普适性,但总体来说非常好。点赞! - SingleNegationElimination
5
哇,太可怕了!不过,你确实说过不建议这样做,而且这个答案确实很好地回答了问题。干得好! - Vanessa Phipps
9
很不幸,它不能处理这种情况
ast.literal_eval('true')或ast.literal_eval('TRUE') 会引发错误
raise ValueError('malformed string')
不过解决方法很简单,只需使用 ast.literal_eval(to_test.title()) 即可。
- Bhushan
它也适用于Unicode吗?在我的Django视图中,我有一个传入的值,我想将其更改为布尔值,但它会抛出一个格式不正确的字符串异常。 - praxmon
太棒了,谢谢。 - aasmpro
显示剩余2条评论

92

警告:除非您确实知道如何处理以下代码,请勿使用。请阅读附带的免责声明,并确保您信任输入,因为在不可信输入上使用此代码可能会破坏您的数据和/或导致您失去工作。

如果您知道字符串将是"True""False"之一,那么您可以直接使用eval(s)

>>> eval("True")
True
>>> eval("False")
False

只有在您确信字符串内容时才使用它,因为如果字符串不包含有效的 Python 代码,它将引发异常,并且将执行字符串中包含的代码。


22
那个字符串会从某个地方得到。如果eval(os.environ["LOL"])返回True:#可能永远不会执行到这里。也可能会刷掉你公司的信用卡。 - nurettin
4
因此,我的评论是只有在您确信字符串内容的情况下才使用它。 - Joel Croteau
12
有很多更安全的选项可供选择,为什么要在简单字符串比较中使用 eval?虽然你永远无法百分之百确定一段代码会在未来保持相同的行为,但如果你坚持使用 eval,那么灾难或许就近在眼前。 - slajma
2
这就是我在谷歌上搜索的正确答案。eval("True") = True和eval("False") = False。很简单。我用它来检查配置文件中的布尔值。 - Kris M
3
一方面,我认为应该使用大写字母“警告”。另一方面,如果有人愚蠢到不经思考地复制粘贴答案,他们也应该被黑客攻击。 - MuhsinFatih
显示剩余4条评论

28

注意: 永远不要使用 eval() 直接或间接地从用户那里接受输入,因为它容易被滥用:

eval('os.system(‘rm -rf /’)')

但是好消息是,研究也发现,eval() 并不是邪恶的,对于可信代码来说,完全可以使用。你可以使用它将布尔字符串(例如 "False""True")转换为布尔类型。


我想分享一下我的简单解决方案:使用 eval()。如果字符串完全符合标题格式 TrueFalse(始终以首字母大写开头),它将把字符串转换为正确的布尔类型;否则该函数将引发错误。

例如:

>>> eval('False')
False

>>> eval('True')
True

当然,对于动态变量,您可以简单地使用.title()来格式化布尔字符串。

>>> x = 'true'
>>> eval(x.title())
True

这将会抛出一个错误。

>>> eval('true')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'true' is not defined

>>> eval('false')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'false' is not defined

11
哇,对于任何找到这条消息的人:不要将其用于除简单脚本之外的任何内容。如果您在任何严肃的应用程序中使用它,将会面临各种意外的代码执行问题。想象一下这样一个场景,您从用户那里解析输入并将字符串转换为布尔值。在这种情况下,攻击者基本上可以执行您的代码所能执行的所有操作。不相信?试试这个:import os eval("os.getcwd()") - Martin Braun
2
@MartinBraun 哦,是的,研究发现你可以执行这个 eval('os.system(‘rm -rf /’)') 并删除该目录中的所有文件。然而,对于可信代码来说,eval() 是完全可以接受的,它并不是真正的邪恶。所以我最好写个注意事项提醒大家小心使用。 - Shift 'n Tab
literal_eval 怎么样? - Nishant

21
有一个优雅的解决方案,使用pydantic
对于pydantic >=2
from pydantic import TypeAdapter
    
>>> TypeAdapter(bool).validate_python("true")
True

>>> TypeAdapter(bool).validate_python("off")
False

对于pydantic <2版本:

import pydantic
    
>>> pydantic.parse_obj_as(bool, "true")
True

>>> pydantic.parse_obj_as(bool, "off")
False

21

这个版本保留了像 int(value) 这样的构造函数的语义,并提供了一种定义可接受字符串值的简单方法。

valid = {'true': True, 't': True, '1': True,
         'false': False, 'f': False, '0': False,
         }

def to_bool(value):
    """Convert string value to boolean."""

    if isinstance(value, bool):
        return value

    if not isinstance(value, basestring):
        raise ValueError('invalid literal for boolean. Not a string.')

    lower_value = value.lower()
    if lower_value in valid:
        return valid[lower_value]
    else:
        raise ValueError('invalid literal for boolean: "%s"' % value)


# Test cases
assert to_bool('true'), '"true" is True' 
assert to_bool('True'), '"True" is True' 
assert to_bool('TRue'), '"TRue" is True' 
assert to_bool('TRUE'), '"TRUE" is True' 
assert to_bool('T'), '"T" is True' 
assert to_bool('t'), '"t" is True' 
assert to_bool('1'), '"1" is True' 
assert to_bool(True), 'True is True' 
assert to_bool(u'true'), 'unicode "true" is True'

assert to_bool('false') is False, '"false" is False' 
assert to_bool('False') is False, '"False" is False' 
assert to_bool('FAlse') is False, '"FAlse" is False' 
assert to_bool('FALSE') is False, '"FALSE" is False' 
assert to_bool('F') is False, '"F" is False' 
assert to_bool('f') is False, '"f" is False' 
assert to_bool('0') is False, '"0" is False' 
assert to_bool(False) is False, 'False is False'
assert to_bool(u'false') is False, 'unicode "false" is False'

# Expect ValueError to be raised for invalid parameter...
try:
    to_bool('')
    to_bool(12)
    to_bool([])
    to_bool('yes')
    to_bool('FOObar')
except ValueError, e:
    pass

6
注意:你最后的“测试用例”会在第一次调用时出错,并且不能测试其他情况。此外,如果没有引发错误,它也不会失败。 - augurar
1
valid的定义应该放在函数外面,否则dict将在每次调用时重新构建,从而消除了使用dict的大部分性能优势。 - ShadowRanger

17

你可以像这样做:

my_string = "false"
val = (my_string == "true")

括号中的位将求值为False。这只是在不必进行实际函数调用的情况下执行它的另一种方式。


1
这个例子中的 val = "false" 行是在做什么?它为什么在那里?它是什么意思? - S.Lott
这正是我所寻找的,从文件中评估输入字段,并根据结果存储布尔值。谢谢。 - jimh

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