Having issue filtering my result dataframe with an or condition. I want my result df to extract all column var values that are above 0.25 and below -0.25.
This logic below gives me an ambiguous truth value however it work when I split this filtering in two separate operations. What is happening here? not sure where to use the suggested a.empty(), a.bool(), a.item(),a.any() or a.all().
result = result[(result['var']>0.25) or (result['var']<-0.25)]
result = result[(result['var']>0.25)|(result['var']<-0.25)]
对于此类数据结构,它们会重载以生成元素级or(或and)。
只是为该语句添加更多解释:
当您想获取的时bool,将引发异常pandas.Series:
>>>import pandas as pd
>>> x = pd.Series([1])>>> bool(x)ValueError:The truth value of a Seriesis ambiguous.Use a.empty, a.bool(), a.item(), a.any()or a.all().
什么你打是一处经营隐含转换的操作数bool(你用or,但它也恰好为and,if和while):
>>> x or x
ValueError:The truth value of a Seriesis ambiguous.Use a.empty, a.bool(), a.item(), a.any()or a.all().>>> x and x
ValueError:The truth value of a Seriesis ambiguous.Use a.empty, a.bool(), a.item(), a.any()or a.all().>>>if x:...print('fun')ValueError:The truth value of a Seriesis ambiguous.Use a.empty, a.bool(), a.item(), a.any()or a.all().>>>while x:...print('fun')ValueError:The truth value of a Seriesis ambiguous.Use a.empty, a.bool(), a.item(), a.any()or a.all().
The or and and python statements require truth-values. For pandas these are considered ambiguous so you should use “bitwise” | (or) or & (and) operations:
result = result[(result['var']>0.25) | (result['var']<-0.25)]
These are overloaded for these kind of datastructures to yield the element-wise or (or and).
Just to add some more explanation to this statement:
The exception is thrown when you want to get the bool of a pandas.Series:
>>> import pandas as pd
>>> x = pd.Series([1])
>>> bool(x)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
What you hit was a place where the operator implicitly converted the operands to bool (you used or but it also happens for and, if and while):
>>> x or x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> x and x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> if x:
... print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> while x:
... print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
Besides these 4 statements there are several python functions that hide some bool calls (like any, all, filter, …) these are normally not problematic with pandas.Series but for completeness I wanted to mention these.
In your case the exception isn’t really helpful, because it doesn’t mention the right alternatives. For and and or you can use (if you want element-wise comparisons):
The alternatives mentioned in the Exception are more suited if you encountered it when doing if or while. I’ll shortly explain each of these:
If you want to check if your Series is empty:
>>> x = pd.Series([])
>>> x.empty
True
>>> x = pd.Series([1])
>>> x.empty
False
Python normally interprets the length of containers (like list, tuple, …) as truth-value if it has no explicit boolean interpretation. So if you want the python-like check, you could do: if x.size or if not x.empty instead of if x.
If your Series contains one and only one boolean value:
If you want to check the first and only item of your Series (like .bool() but works even for not boolean contents):
>>> x = pd.Series([100])
>>> x.item()
100
If you want to check if all or any item is not-zero, not-empty or not-False:
>>> x = pd.Series([0, 1, 2])
>>> x.all() # because one element is zero
False
>>> x.any() # because one (or more) elements are non-zero
True
回答 1
对于布尔逻辑,请使用&和|。
np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))>>> df
A B C
01.7640520.4001570.97873812.2408931.867558-0.97727820.950088-0.151357-0.10321930.4105990.1440441.45427440.7610380.1216750.443863>>> df.loc[(df.C >0.25)|(df.C <-0.25)]
A B C
01.7640520.4001570.97873812.2408931.867558-0.97727830.4105990.1440441.45427440.7610380.1216750.443863
# Any value in either column is True?(df.C >0.25).any()or(df.C <-0.25).any()True# All values in either column is True?(df.C >0.25).all()or(df.C <-0.25).all()False
一种实现相同目的的复杂方法是将所有这些列压缩在一起,并执行适当的逻辑。
>>> df[[any([a, b])for a, b in zip(df.C >0.25, df.C <-0.25)]]
A B C
01.7640520.4001570.97873812.2408931.867558-0.97727830.4105990.1440441.45427440.7610380.1216750.443863
When you have multiple criteria, you will get multiple columns returned. This is why the the join logic is ambiguous. Using and or or treats each column separately, so you first need to reduce that column to a single boolean value. For example, to see if any value or all values in each of the columns is True.
# Any value in either column is True?
(df.C > 0.25).any() or (df.C < -0.25).any()
True
# All values in either column is True?
(df.C > 0.25).all() or (df.C < -0.25).all()
False
One convoluted way to achieve the same thing is to zip all of these columns together, and perform the appropriate logic.
>>> df[[any([a, b]) for a, b in zip(df.C > 0.25, df.C < -0.25)]]
A B C
0 1.764052 0.400157 0.978738
1 2.240893 1.867558 -0.977278
3 0.410599 0.144044 1.454274
4 0.761038 0.121675 0.443863
import operator
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))
df.loc[operator.or_(df.C >0.25, df.C <-0.25)]
A B C
01.7640520.4001570.97873812.2408931.867558-0.97727830.4105990.1440441.45427440.7610380.1216750.4438
This excellent answer explains very well what is happening and provides a solution. I would like to add another solution that might be suitable in similar cases: using the query method:
result = result.query("(var > 0.25) or (var < -0.25)")
(Some tests with a dataframe I’m currently working with suggest that this method is a bit slower than using the bitwise operators on series of booleans: 2 ms vs. 870 µs)
A piece of warning: At least one situation where this is not straightforward is when column names happen to be python expressions. I had columns named WT_38hph_IP_2, WT_38hph_input_2 and log2(WT_38hph_IP_2/WT_38hph_input_2) and wanted to perform the following query: "(log2(WT_38hph_IP_2/WT_38hph_input_2) > 1) and (WT_38hph_IP_2 > 20)"
I obtained the following exception cascade:
KeyError: 'log2'
UndefinedVariableError: name 'log2' is not defined
ValueError: "log2" is not a supported function
I guess this happened because the query parser was trying to make something from the first two columns instead of identifying the expression with the name of the third column.
I encountered the same error and got stalled with a pyspark dataframe for few days, I was able to resolve it successfully by filling na values with 0 since I was comparing integer values from 2 fields.
Sadly, parsed_args.my_bool evaluates to True. This is the case even when I change cmd_line to be ["--my_bool", ""], which is surprising, since bool("") evalutates to False.
How can I get argparse to parse "False", "F", and their lower-case variants to be False?
回答 0
另一个解决方案使用了先前的建议,但存在来自argparse以下情况的“正确”解析错误:
def str2bool(v):if isinstance(v, bool):return v
if v.lower()in('yes','true','t','y','1'):returnTrueelif v.lower()in('no','false','f','n','0'):returnFalseelse:raise argparse.ArgumentTypeError('Boolean value expected.')
and still use a default value (specific to the user settings). One (indirectly related) downside with that approach is that the ‘nargs’ might catch a positional argument — see this related question and this argparse bug report.
import argparse
parser = argparse.ArgumentParser(description="Parse bool")
parser.add_argument("--do-something", default=False, action="store_true", help="Flag to do something")
args = parser.parse_args()if args.do_something:print("Do something")else:print("Don't do something")print("Check that args.do_something="+ str(args.do_something)+" is always a bool")
Here is another variation without extra row/s to set default values. The bool always have a value assigned so that it can be used in logical statements without pre-checks.
import argparse
parser = argparse.ArgumentParser(description="Parse bool")
parser.add_argument("--do-something", default=False, action="store_true" , help="Flag to do something")
args = parser.parse_args()
if args.do_something:
print("Do something")
else:
print("Don't do something")
print("Check that args.do_something=" + str(args.do_something) + " is always a bool")
关于什么type=bool以及type='bool'可能意味着什么似乎有些困惑。一个(或两个)是否应该表示“运行函数bool()或”返回布尔值”?就目前而言,它type='bool'毫无意义。 add_argument给出'bool' is not callable错误,与您使用type='foobar'或相同type='int'。
def str2bool(v):#susendberg's functionreturn v.lower()in("yes","true","t","1")
p = argparse.ArgumentParser()
p.register('type','bool',str2bool)# add type keyword to registries
p.add_argument('-b',type='bool')# do not use 'type=bool'# p.add_argument('-b',type=str2bool) # works just as well
p.parse_args('-b false'.split())Namespace(b=False)
There seems to be some confusion as to what type=bool and type='bool' might mean. Should one (or both) mean ‘run the function bool(), or ‘return a boolean’? As it stands type='bool' means nothing. add_argument gives a 'bool' is not callable error, same as if you used type='foobar', or type='int'.
But argparse does have registry that lets you define keywords like this. It is mostly used for action, e.g. `action=’store_true’. You can see the registered keywords with:
There are lots of actions defined, but only one type, the default one, argparse.identity.
This code defines a ‘bool’ keyword:
def str2bool(v):
#susendberg's function
return v.lower() in ("yes", "true", "t", "1")
p = argparse.ArgumentParser()
p.register('type','bool',str2bool) # add type keyword to registries
p.add_argument('-b',type='bool') # do not use 'type=bool'
# p.add_argument('-b',type=str2bool) # works just as well
p.parse_args('-b false'.split())
Namespace(b=False)
parser.register() is not documented, but also not hidden. For the most part the programmer does not need to know about it because type and action take function and class values. There are lots of stackoverflow examples of defining custom values for both.
In case it isn’t obvious from the previous discussion, bool() does not mean ‘parse a string’. From the Python documentation:
bool(x): Convert a value to a Boolean, using the standard truth testing procedure.
Contrast this with
int(x): Convert a number or string x to an integer.
Does anyone know how to do convert from a string to a boolean in Python? I found this link. But it doesn’t look like a proper way to do it. I.e. using built-in functionality, etc.
The reason I’m asking this is because I learned about int("string") from here. But when trying bool("string") it always returns True:
You could also make your function explicitly check against a True list of words and a False list of words. Then if it is in neither list, you could throw an exception.
Starting with Python 2.6, there is now ast.literal_eval:
>>> import ast
>>> help(ast.literal_eval)
Help on function literal_eval in module ast:
literal_eval(node_or_string)
Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the following
Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
and None.
Which seems to work, as long as you’re sure your strings are going to be either "True" or "False":
>>> ast.literal_eval("True")
True
>>> ast.literal_eval("False")
False
>>> ast.literal_eval("F")
Traceback (most recent call last):
File "", line 1, in
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'
I wouldn’t normally recommend this, but it is completely built-in and could be the right thing depending on your requirements.
If you know the string will be either "True" or "False", you could just use eval(s).
>>> eval("True")
True
>>> eval("False")
False
Only use this if you are sure of the contents of the string though, as it will throw an exception if the string does not contain valid Python, and will also execute code contained in the string.
回答 6
此版本保留了int(value)等构造函数的语义,并提供了一种定义可接受的字符串值的简便方法。
def to_bool(value):
valid ={'true':True,'t':True,'1':True,'false':False,'f':False,'0':False,}if isinstance(value, bool):return value
ifnot isinstance(value, basestring):raiseValueError('invalid literal for boolean. Not a string.')
lower_value = value.lower()if lower_value in valid:return valid[lower_value]else:raiseValueError('invalid literal for boolean: "%s"'% value)# Test casesassert 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')isFalse,'"false" is False'assert to_bool('False')isFalse,'"False" is False'assert to_bool('FAlse')isFalse,'"FAlse" is False'assert to_bool('FALSE')isFalse,'"FALSE" is False'assert to_bool('F')isFalse,'"F" is False'assert to_bool('f')isFalse,'"f" is False'assert to_bool('0')isFalse,'"0" is False'assert to_bool(False)isFalse,'False is False'assert to_bool(u'false')isFalse,'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')exceptValueError, e:pass
This version keeps the semantics of constructors like int(value) and provides an easy way to define acceptable string values.
def to_bool(value):
valid = {'true': True, 't': True, '1': True,
'false': False, 'f': False, '0': False,
}
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
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"):returnTrueif str(value).lower()in("no","n","false","f","0","0.0","","none","[]","{}"):returnFalseraiseException('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>>>
Here’s is my version. It checks against both positive and negative values lists, raising an exception for unknown values. And it does not receive a string, but any type should do.
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))
Sample runs:
>>> 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
>>>
If this is too wide, it can be refined by testing the type result. If the yaml-returned type is a str, then it can’t be cast to any other type (that I can think of anyway), so you could handle that separately, or just let it be true.
I won’t make any guesses at speed, but since I am working with yaml data under Qt gui anyway, this has a nice symmetry.
回答 10
我不同意这里的任何解决方案,因为它们太宽容了。这通常不是解析字符串时想要的。
所以这是我正在使用的解决方案:
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']:returnTrueelif bool_str.lower()in['false','f','0']:returnFalse#if here we couldn't parse itraiseValueError("%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
I don’t agree with any solution here, as they are too permissive. This is not normally what you want when parsing a string.
So here the solution I’m using:
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)
And the results:
>>> [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
Just to be clear because it looks as if my answer offended somebody somehow:
The point is that you don’t want to test for only one value and assume the other. I don’t think you always want to map Absolutely everything to the non parsed value. That produces error prone code.
So, if you know what you want code it in.
回答 11
dict(实际上是defaultdict)为您提供了一种非常简单的方法来完成此操作:
from collections import defaultdict
bool_mapping = defaultdict(bool)# Will give you False for non-found valuesfor val in['True','yes',...]:
bool_mapping[val]=Trueprint(bool_mapping['True'])# Trueprint(bool_mapping['kitten'])# False
A dict (really, a defaultdict) gives you a pretty easy way to do this trick:
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
It’s really easy to tailor this method to the exact conversion behavior you want — you can fill it with allowed Truthy and Falsy values and let it raise an exception (or return None) when a value isn’t found, or default to True, or default to False, or whatever you want.
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 isTrueor val isFalse:return val
falseItems =["false","f","no","n","none","0","[]","{}",""]returnnot str( val ).strip().lower()in falseItems
You probably already have a solution but for others who are looking for a method to convert a value to a boolean value using “standard” false values including None, [], {}, and “” in addition to false, no , and 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
a='True'if a isTrue:print'a is True, a type is', type(a)else:print"a isn't True, a type is", type(a)
b = eval(a)if b isTrue:print'b is True, b type is', type(b)else:print"b isn't True, b type is", type(b)
和输出:
a isn't True, a type is <type 'str'>
b is True, b type is <type 'bool'>
a='True'
if a is True:
print 'a is True, a type is', type(a)
else:
print "a isn't True, a type is", type(a)
b = eval(a)
if b is True:
print 'b is True, b type is', type(b)
else:
print "b isn't True, b type is", type(b)
and the output:
a isn't True, a type is <type 'str'>
b is True, b type is <type 'bool'>
回答 14
另一个选择
from ansible.module_utils.parsing.convert_bool import boolean
boolean('no')# False
boolean('yEs')# True
boolean('true')# True
But in production if you don’t need ansible and all its dependencies, a good idea is to look at its source code and copy part of the logic that you need.
The usual rule for casting to a bool is that a few special literals (False, 0, 0.0, (), [], {}) are false and then everything else is true, so I recommend the following:
def boolify(val):
if (isinstance(val, basestring) and bool(val)):
return not val in ('False', '0', '0.0')
else:
return bool(val)
回答 16
这是我写的版本。将其他几种解决方案合并为一个。
def to_bool(value):"""
Converts 'something' to boolean. Raises exception if it gets a string it doesn't handle.
Case is ignored for strings. These string values are handled:
True: 'True', "1", "TRue", "yes", "y", "t"
False: "", "0", "faLse", "no", "n", "f"
Non-string values are passed to bool.
"""if type(value)== type(''):if value.lower()in("yes","y","true","t","1"):returnTrueif value.lower()in("no","n","false","f","0",""):returnFalseraiseException('Invalid value for boolean conversion: '+ value)return bool(value)
This is the version I wrote. Combines several of the other solutions into one.
def to_bool(value):
"""
Converts 'something' to boolean. Raises exception if it gets a string it doesn't handle.
Case is ignored for strings. These string values are handled:
True: 'True', "1", "TRue", "yes", "y", "t"
False: "", "0", "faLse", "no", "n", "f"
Non-string values are passed to bool.
"""
if type(value) == type(''):
if value.lower() in ("yes", "y", "true", "t", "1"):
return True
if value.lower() in ("no", "n", "false", "f", "0", ""):
return False
raise Exception('Invalid value for boolean conversion: ' + value)
return bool(value)
If it gets a string it expects specific values, otherwise raises an Exception. If it doesn’t get a string, just lets the bool constructor figure it out. Tested these cases:
If you like me just need boolean from variable which is string. You can use distils as mentioned earlier by @jzwiener. However I could not import and use the module as he suggested.
Instead I end up using it this way on python3.7
from distutils import util # to handle str to bool conversion
enable_deletion = 'False'
enable_deletion = bool(util.strtobool(enable_deletion))
distutils is part of the python std lib so no need of installation. Which is great!👍
>>> eval('true')Traceback(most recent call last):File"<stdin>", line 1,in<module>File"<string>", line 1,in<module>NameError: name 'true'isnot defined
>>> eval('false')Traceback(most recent call last):File"<stdin>", line 1,in<module>File"<string>", line 1,in<module>NameError: name 'false'isnot defined
I would like to share my simple solution: use the eval(). It will convert the string True and False to proper boolean type IF the string is exactly in title format True or False always first letter capital or else the function will raise an error.
e.g.
>>> eval('False')
False
>>> eval('True')
True
Of course for dynamic variable you can simple use the .title() to format the boolean string.
>>> x = 'true'
>>> eval(x.title())
True
This will throw an error.
>>> 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
here’s a hairy, built in way to get many of the same answers. Note that although python considers "" to be false and all other strings to be true, TCL has a very different idea about things.
>>> 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 /']"
>>>
A good thing about this is that it is fairly forgiving about the values you can use. It’s lazy about turning strings into values, and it’s hygenic about what it accepts and rejects(notice that if the above statement were given at a tcl prompt, it would erase the users hard disk).
the bad thing is that it requires that Tkinter be available, which is usually, but not universally true, and more significantly, requires that a Tk instance be created, which is comparatively heavy.
What is considered true or false depends on the behavior of the Tcl_GetBoolean, which considers 0, false, no and off to be false and 1, true, yes and on to be true, case insensitive. Any other string, including the empty string, cause an exception.
By using Python’s built-in eval() function and the .capitalize() method, you can convert any “true” / “false” string (regardless of initial capitalization) to a true Python boolean.