在Python中如何将字符串转换为布尔值?以下尝试会返回 True
:
>>> bool("False")
True
这里有一个棘手的内置方法可以获得许多相同的答案。请注意,尽管Python认为""
是假的,而所有其他字符串都是真的,但TCL对事物有非常不同的看法。
>>> import Tkinter
>>> tk = Tkinter.Tk()
>>> var = Tkinter.BooleanVar(tk)
>>> var.set("false")
>>> var.get()
False
>>> var.set("1")
>>> var.get()
True
>>> var.set("[exec 'rm -r /']")
>>> var.get()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.5/lib-tk/Tkinter.py", line 324, in get
return self._tk.getboolean(self._tk.globalgetvar(self._name))
_tkinter.TclError: 0expected boolean value but got "[exec 'rm -r /']"
>>>
关于这个好的一点是,它对可以使用的值相当宽容。它将字符串转换为值的方式很慵懒,但在接受和拒绝方面非常谨慎(请注意,如果在tcl提示符上给出上述语句,它将抹掉用户的硬盘)。
坏处是它要求Tkinter可用,这通常是但不普遍适用,并且更重要的是需要创建一个Tk实例,这相对较繁重。
什么被认为是真或假取决于Tcl_GetBoolean
的行为,它将0
,false
,no
和off
视为假,将1
,true
,yes
和on
视为真,不区分大小写。任何其他字符串,包括空字符串,都会引发异常。
我整理了一些代码用于评估字符串的真实性:
def as_bool(val):
if val:
try:
if not int(val): val=False
except: pass
try:
if val.lower()=="false": val=False
except: pass
return bool(val)
与使用eval
相比,结果几乎相同但更安全。
这是一个使用Django Rest Framework (DRF) 3.14代码的答案。
你可以选择:
from rest_framework.fields import BooleanField
f = BooleanField(allow_null=True)
test_values = [ True, "True", "1", 1, -1, 1.0, "true", "t", "on",
None, "null", "NULL",
False, "False", "0", 0, "false", "f", 0.0, "off" ]
for item in test_values:
r = f.to_internal_value(item)
print(r)
# a shorter version
from rest_framework.fields import BooleanField
test_values = [ True, "True", "1", 1, -1, 1.0, "true", "t", "on",
None, "null", "NULL",
False, "False", "0", 0, "false", "f", 0.0, "off" ]
for item in test_values:
print(BooleanField(allow_null=True).to_internal_value(item))
或者你可以调整布尔字段的代码,使其适合你的需求。以下是 DRF 3.x 中 BooleanField 类的实际代码:
# from rest_framework.fields
# ...
class BooleanField(Field):
default_error_messages = {
'invalid': _('Must be a valid boolean.')
}
default_empty_html = False
initial = False
TRUE_VALUES = {
't', 'T',
'y', 'Y', 'yes', 'Yes', 'YES',
'true', 'True', 'TRUE',
'on', 'On', 'ON',
'1', 1,
True
}
FALSE_VALUES = {
'f', 'F',
'n', 'N', 'no', 'No', 'NO',
'false', 'False', 'FALSE',
'off', 'Off', 'OFF',
'0', 0, 0.0,
False
}
NULL_VALUES = {'null', 'Null', 'NULL', '', None}
def to_internal_value(self, data):
try:
if data in self.TRUE_VALUES:
return True
elif data in self.FALSE_VALUES:
return False
elif data in self.NULL_VALUES and self.allow_null:
return None
except TypeError: # Input is an unhashable type
pass
self.fail('invalid', input=data)
def to_representation(self, value):
if value in self.TRUE_VALUES:
return True
elif value in self.FALSE_VALUES:
return False
if value in self.NULL_VALUES and self.allow_null:
return None
return bool(value)
# ...
对于一些特定的情况或者数据处理时,最高评分的答案是可行的。然而,由于在Python中自定义对象可以覆盖__eq__
等于检查,因此存在一个重要的陷阱。考虑下面故意过于简化的示例:
In [1]: class MyString:
...: def __init__(self, value):
...: self.value = value
...: def __eq__ (self, obj):
...: if hasattr(obj, 'value'):
...: return obj.value == self.value
...: return False
...:
In [2]: v = MyString("True")
In [3]: v == "True"
Out[3]: False
MyString
或实现各种本地字符串方法、repr等,使得MyString
实例大多数情况下的行为与字符串完全相同,但在相等性检查中具有特殊的额外value
步骤,那么简单地使用== 'True'
将会失败,很可能这会是用户视角下的一个静默错误。MyString
,你可以编写类似以下代码的内容:def validate(s):
if isinstance(s, str):
return s == 'True'
elif isinstance(s, MyString):
return s.value == 'True' # <-- business logic
...
raise ValueError(f"Type {type(s)} not supported for validation.")
另一个经常使用的模式是反向透视,其中您为验证定义了确切的行为,但您有一个辅助函数,强制将其转换为适合于单个验证行为的类型,例如:
def to_str(s):
if isinstance(s, str):
return s
elif isinstance(s, MyString):
return s.value
...
raise ValueError(f"Unsupported type {type(s)}")
def validate(s):
return to_str(s) == 'True'
看起来我们正在添加很多样板和冗言冗语。我们可以轻率地通过说,“如果你只能写s == 'True'
,为什么要写那么多?”来表达批评 - 但这忽略了一个重点,当你在验证某些内容时,你需要确保所有的先决条件都满足以便应用验证逻辑。如果你可以假设一些数据是纯粹的str
类型并且你不需要进行任何前提条件检查(比如类型),那就太好了 - 但这是非常罕见的情况,并且将一般情况描述为一个超级简短和简洁的相等性检查是具有误导性的。
def str2bool(str):
if isinstance(str, basestring) and str.lower() in ['0','false','no']:
return False
else:
return bool(str)
我喜欢使用三元运算符来完成这个任务,因为它更加简洁,而且感觉不需要超过一行。
True if my_string=="True" else False
my_string == "True"
做的事情完全相同,但两个选项都无法处理不正确的输入(即“true”)。 - Neuron我只是不得不这样做...可能有点晚了 - 但愿有人会觉得有用
def str_to_bool(input, default):
"""
| Default | not_default_str | input | result
| T | "false" | "true" | T
| T | "false" | "false" | F
| F | "true" | "true" | T
| F | "true" | "false" | F
"""
if default:
not_default_str = "false"
else:
not_default_str = "true"
if input.lower() == not_default_str:
return not default
else:
return default
eval()
函数和.capitalize()
方法,您可以将任何“true”/“false”字符串(不管初始大小写)转换为Python中的真正布尔值。true_false = "trUE"
type(true_false)
# OUTPUT: <type 'str'>
true_false = eval(true_false.capitalize())
type(true_false)
# OUTPUT: <type 'bool'>
#\nshutil.rmtree('/someImportantDirectory')
会发生什么?(不要尝试!) - mastoveval
函数,这实在是太冒险了,很可能存在漏洞。 - mastoveval
,这些字符串可能会帮助某人接管整个系统。 - mastov
bool("string")
时,它总是返回True
...除了空字符串bool("")
。 - FiddleStix