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

1
使用包str2bool pip install str2bool

0

这里有一个棘手的内置方法可以获得许多相同的答案。请注意,尽管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的行为,它将0falsenooff视为假,将1trueyeson视为真,不区分大小写。任何其他字符串,包括空字符串,都会引发异常。


0

我整理了一些代码用于评估字符串的真实性:

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相比,结果几乎相同但更安全。


0

这是一个使用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)

# ...

0

对于一些特定的情况或者数据处理时,最高评分的答案是可行的。然而,由于在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类型并且你不需要进行任何前提条件检查(比如类型),那就太好了 - 但这是非常罕见的情况,并且将一般情况描述为一个超级简短和简洁的相等性检查是具有误导性的。


0
def str2bool(str):
  if isinstance(str, basestring) and str.lower() in ['0','false','no']:
    return False
  else:
    return bool(str)

想法:检查您是否希望将字符串评估为False;否则,bool()对于任何非空字符串都返回True。

0

我喜欢使用三元运算符来完成这个任务,因为它更加简洁,而且感觉不需要超过一行。

True if my_string=="True" else False

4
它比 my_string == 'True' 更加简洁吗? - S. de Melo
my_string == "True" 做的事情完全相同,但两个选项都无法处理不正确的输入(即“true”)。 - Neuron
3
不太确定该说什么,10年前的我显然是个白痴… - Clayton Rabenda

0

我只是不得不这样做...可能有点晚了 - 但愿有人会觉得有用

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

-8
通过使用Python内置的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'>

5
如果字符串包含#\nshutil.rmtree('/someImportantDirectory')会发生什么?(不要尝试!) - mastov
1
除了没有提到危险(这已经使得这个答案很糟糕了):您建议事先对输入进行清理?这将破坏此方法的简单性,而这正是它的主要优点。 - mastov
6
仅仅因为一件如此简单的事情就使用 eval 函数,这实在是太冒险了,很可能存在漏洞。 - mastov
1
不是所有的代码,但通常涉及将字符串转换为其他类型的代码确实*不在您的控制范围内。您可能甚至没有意识到这一点。您可能会说:“这是我的数据库(或配置文件),它是我的系统的一部分,在我的控制之下。”然后,您会让某个其他模块访问数据库,因为:“有什么伤害?只是一些包含字符串的表格。”但是使用eval,这些字符串可能会帮助某人接管整个系统。 - mastov
@Overcode,仅仅说某些事情“超出了糟糕的实践”,而不给出理由(特别是排除安全问题时)是超出了糟糕的实践。帮助我们学习为什么这些做法是糟糕的,而不仅仅是说它们是糟糕的。 - elPastor
显示剩余5条评论

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