musiałem zająć się tą sprawą jest zapewnienie, że „1.0” zostanie zamienione na „1”, gdy starałem się określić różnice między dwoma dokumentami XML. Więc napisałem tę funkcję, aby mi pomóc. Sądzę również, że niektóre z innych rozwiązań zawiodą, gdy literał literowy będzie "prawdziwy" lub "fałszywy". W każdym razie funkcja ta działa bardzo dobrze dla mnie. Mam nadzieję, że ci to pomoże.
from ast import literal_eval
def convertString(s):
'''
This function will try to convert a string literal to a number or a bool
such that '1.0' and '1' will both return 1.
The point of this is to ensure that '1.0' and '1' return as int(1) and that
'False' and 'True' are returned as bools not numbers.
This is useful for generating text that may contain numbers for diff
purposes. For example you may want to dump two XML documents to text files
then do a diff. In this case you would want <blah value='1.0'/> to match
<blah value='1'/>.
The solution for me is to convert the 1.0 to 1 so that diff doesn't see a
difference.
If s doesn't evaluate to a literal then s will simply be returned UNLESS the
literal is a float with no fractional part. (i.e. 1.0 will become 1)
If s evaluates to float or a float literal (i.e. '1.1') then a float will be
returned if and only if the float has no fractional part.
if s evaluates as a valid literal then the literal will be returned. (e.g.
'1' will become 1 and 'False' will become False)
'''
if isinstance(s, str):
# It's a string. Does it represnt a literal?
#
try:
val = literal_eval(s)
except:
# s doesn't represnt any sort of literal so no conversion will be
# done.
#
val = s
else:
# It's already something other than a string
#
val = s
##
# Is the float actually an int? (i.e. is the float 1.0 ?)
#
if isinstance(val, float):
if val.is_integer():
return int(val)
# It really is a float
return val
return val
Wyjście testów jednostkowych tej funkcji powoduje:
convertString("1")=1; we expect 1
convertString("1.0")=1; we expect 1
convertString("1.1")=1.1; we expect 1.1
convertString("010")=8; we expect 8
convertString("0xDEADBEEF")=3735928559; we expect 3735928559
convertString("hello")="hello"; we expect "hello"
convertString("false")="false"; we expect "false"
convertString("true")="true"; we expect "true"
convertString("False")=False; we expect False
convertString("True")=True; we expect True
convertString(sri.gui3.xmlSamples.test_convertString.A)=sri.gui3.xmlSamples.test_convertString.A; we expect sri.gui3.xmlSamples.test_convertString.A
convertString(<function B at 0x7fd9e2f27ed8>)=<function B at 0x7fd9e2f27ed8>; we expect <function B at 0x7fd9e2f27ed8>
convertString(1)=1; we expect 1
convertString(1.0)=1; we expect 1
convertString(1.1)=1.1; we expect 1.1
convertString(3735928559)=3735928559; we expect 3735928559
convertString(False)=False; we expect False
convertString(True)=True; we expect True
Jednostka kodu testu następuje:
import unittest
# just class for testing that the class gets returned unmolested.
#
class A: pass
# Just a function
#
def B(): pass
class Test(unittest.TestCase):
def setUp(self):
self.conversions = [
# input | expected
('1' ,1 ),
('1.0' ,1 ), # float with no fractional part
('1.1' ,1.1 ),
('010' ,8 ), # octal
('0xDEADBEEF',0xDEADBEEF), # hex
('hello' ,'hello' ),
('false' ,'false' ),
('true' ,'true' ),
('False' ,False ), # bool
('True' ,True ), # bool
(A ,A ), # class
(B ,B ), # function
(1 ,1 ),
(1.0 ,1 ), # float with no fractional part
(1.1 ,1.1 ),
(0xDEADBEEF ,0xDEADBEEF),
(False ,False ),
(True ,True ),
]
def testName(self):
for s,expected in self.conversions:
rval = convertString(s)
print 'convertString({s})={rval}; we expect {expected}'.format(**locals())
self.assertEqual(rval, expected)
if __name__ == "__main__":
#import sys;sys.argv = ['', 'Test.testName']
unittest.main()
Oczywiście najpierw należy przetestować dla 'isint()', a następnie przetestować dla 'isfloat()' tylko wtedy, gdy pierwsza zwraca wartość 'False'. –
Najpierw spróbuj isint, a następnie użyj isfloat, ale jeśli użyję isint, wszystkie testy zostaną zaliczone. Czy uważasz, że lepiej jest używać tylko isint()? – ManuParra
To źle dla bardzo dużych liczb. Na przykład float ("10000000000000000.5") to 1e + 16, int (1e + 16) to 1e + 16, ale liczba nie jest int. – Nixon