在 Python 中将字符串转换为布尔值
- 2025-01-16 08:38:00
- admin 原创
- 99
问题描述:
如何在 Python 中将字符串转换为布尔值?此尝试返回True
:
>>> bool("False")
True
解决方案 1:
实际上,你只需将字符串与你期望接受的代表真实的内容进行比较,因此你可以这样做:
s == 'True'
或者检查一大堆值:
s.lower() in ['true', '1', 't', 'y', 'yes', 'yeah', 'yup', 'certainly', 'uh-huh']
使用以下内容时请小心:
>>> bool("foo")
True
>>> bool("")
False
空字符串的计算结果为False
,但其他所有字符串的计算结果为True
。因此,不应将其用于任何类型的解析目的。
解决方案 2:
警告:从 Python 3.12 开始,此答案将不再有效(从 3.10 开始已被弃用)
使用:
bool(distutils.util.strtobool(some_string))
Python 2:
distutils.util.strtobool
Python> = 3,<3.12:
distutils.util.strtobool
Python >=3.12 : 由于PEP 632 – 弃用 distutils 模块,不再是标准库的一部分
真值为 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,))
解决方案 3:
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
明确处理 true 和 false:
您还可以让函数明确检查单词的 True 列表和 False 列表。然后,如果它不在任何一个列表中,您可以抛出异常。
解决方案 4:
JSON 解析器通常还可用于将字符串转换为合理的 Python 类型。
>>> import json
>>> json.loads("false".lower())
False
>>> json.loads("True".lower())
True
解决方案 5:
从Python 2.6开始您可以使用ast.literal_eval
,并且它在Python 3中仍然可用。
评估仅包含 Python 文字或容器显示的表达式节点或字符串。提供的字符串或节点只能由以下 Python 文字结构组成:字符串、字节、数字、元组、列表、字典、集合、布尔值
None
和Ellipsis
。这可用于评估包含 Python 值的字符串,而无需自己解析值。它无法评估任意复杂的表达式,例如涉及运算符或索引的表达式。
过去,该函数曾被记录为“安全”,但没有定义其含义。这是误导。与更通用的 不同,它专门设计用于不执行 Python 代码。
eval()
它没有命名空间、名称查找或调用能力。但它并非免受攻击:相对较小的输入可能会导致内存耗尽或 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'
我通常不会推荐这个,但它是完全内置的,并且根据您的要求可能是正确的。
解决方案 6:
警告:除非您确实知道要用以下代码做什么,否则请不要使用它们。请阅读随附的免责声明,并确保您信任您的输入,因为在不受信任的输入上使用此代码可能会破坏您的数据和/或让您丢掉工作。
如果您知道字符串是"True"
或"False"
,那么您可以直接使用eval(s)
。
>>> eval("True")
True
>>> eval("False")
False
只有当您确定字符串的内容时才使用它,因为如果字符串不包含有效的 Python,它将引发异常,并且还会执行字符串中包含的代码。
解决方案 7:
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
解决方案 8:
eval()
注意:如果它直接或间接地从用户那里获取输入,请不要使用,因为它很容易被滥用:
eval('os.system(‘rm -rf /’)')
但加油!研究还发现这eval()
不是邪恶的,对于TRUSTED CODE来说这是完全可以的。您可以使用它将布尔字符串(例如"False"
和)转换"True"
为布尔类型。
我想分享我的简单解决方案:使用。如果字符串完全符合标题格式或始终首字母大写eval()
,它将把字符串转换为正确的布尔类型,否则该函数将引发错误。True
`FalseTrue
False`
例如
>>> 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
解决方案 9:
此版本保留了 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
解决方案 10:
你可以做类似的事情
my_string = "false"
val = (my_string == "true")
括号中的位将计算为False
。这只是另一种方法,无需进行实际的函数调用。
解决方案 11:
这是我的版本。它检查正值和负值列表,对未知值引发异常。它不接收字符串,但任何类型都可以。
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
>>>
解决方案 12:
一个很酷的简单技巧(基于@Alan Marchiori 发布的内容),但使用 yaml:
import yaml
parsed = yaml.load("true")
print bool(parsed)
如果范围太广,可以通过测试类型结果来改进。如果 yaml 返回的类型是 str,则无法将其转换为任何其他类型(无论如何我能想到的),因此您可以单独处理它,或者让它为真。
我不会对速度做出任何猜测,但由于无论如何我都在 Qt gui 下处理 yaml 数据,所以这具有很好的对称性。
解决方案 13:
字典(实际上是默认字典)可以给你一个非常简单的方法来实现这个技巧:
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
这些技巧还是挺有趣的。
解决方案 14:
我不同意这里的任何解决方案,因为它们太宽容了。这通常不是解析字符串时您想要的。
以下是我使用的解决方案:
def to_bool(bool_str):
"""Parse the string and return the boolean value encoded or raise an exception"""
# replace basestring by str in python 3.x
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
只是为了清楚起见,因为看起来我的回答似乎以某种方式冒犯了某些人:
关键在于你不想只测试一个值而假设另一个值。我认为你并不总是想将所有内容都映射到未解析的值。这会产生容易出错的代码。
因此,如果你知道你想要什么,就把它编码进去。
解决方案 15:
通过使用以下简单的逻辑,您可以将字符串(a = 'true'
例如或'false'
)转换为布尔值。
a = a.lower() == 'true'
如果a == 'true'
那么这将设置a=True
,如果a == 'false'
那么a=False
。
解决方案 16:
另一种选择
from ansible.module_utils.parsing.convert_bool import boolean
boolean('no')
# False
boolean('yEs')
# True
boolean('true')
# True
解决方案 17:
我用
# 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]]
"""
解决方案 18:
您可能已经有了解决方案,但对于其他人来说,他们正在寻找一种将值转换为布尔值的方法,除了 false、no 和 0 之外,还使用“标准”错误值(包括 None、[]、{} 和 "")。
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
解决方案 19:
true
如果您可以控制返回/的实体false
,则一种选择是让它返回1
/0
而不是true
/ false
,然后:
boolean_response = bool(int(response))
额外的转换来int
处理来自网络的响应,它们始终是字符串。
2021 年更新:“始终为字符串”——这是一个幼稚的观察。这取决于库使用的序列化协议。高级库(大多数 Web 开发人员使用的库)的默认序列化通常是先转换为字符串,然后再序列化为字节。然后在另一边,它从字节反序列化为字符串,因此您丢失了任何类型信息。
解决方案 20:
如果您像我一样,只需要字符串变量中的布尔值。您可以按照@jzwiener 所述使用 distils 。但是我无法按照他的建议导入和使用该模块。
相反,我最终在 python3.7 上这样使用它
from distutils import util # to handle str to bool conversion
enable_deletion = 'False'
enable_deletion = bool(util.strtobool(enable_deletion))
distutils 是 python std lib 的一部分,因此无需安装任何东西,这很棒!