Python Style Question
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Thu Oct 30 23:52:49 EDT 2014
Roy Smith wrote:
> In article <54521c8f$0$12982$c3e8da3$5496439d at news.astraweb.com>,
> Steven D'Aprano <steve+comp.lang.python at pearwood.info> wrote:
>
>> Anton wrote:
>>
>> > Let's say I have an incoming list of values *l*. Every element of *l*
>> > can be one of the following options:
>> > 1) an integer value
>> > 2) a string in form of '<int_value>', e.g. '7'
>> > 3) a string with a json serialization of an integer value, e.g. '"7"'
>> > 4) something else that should be ignored
>> >
>> > I need to transform this list into another list with values from
>> > options 1)-3) coerced to int. The code below should do this.
>>
>> I don't particularly like either version. I prefer this:
>>
>> def load_int(obj):
>> if isinstance(obj, int):
>> # Case 1), an int, e.g. 7
>> return obj
>> elif isinstance(obj, str):
>> # Case 2) and 3), a str or JSON serialised int.
>> # E.g. '7' or '"7"'.
>> try:
>> return int(obj)
>> except ValueError:
>> return int(json.loads(obj))
>> raise TypeError('require int or str, got %s' % type(obj).__name__)
>
> Depending on how strictly you're trying to do input validation, the
> int(json.loads(obj)) may not be what you want. It allows well-formed
> json encoding floats, for example.
Really?
py> int(json.loads(json.dumps(23.5)))
23
Damn! You're right.
Back to Plan A:
elif isinstance(obj, str):
try:
return int(obj)
except ValueError:
if obj and obj.startswith('"') and obj.endswith('"'):
return int(obj[1:-1])
raise
But of course even the int() function itself may be a little more flexible
than we might want:
py> int(' 1 ')
1
So I guess the lessons are:
* before writing code, you need to decide what the code is meant to do;
* and that includes what input must be rejected, not just what input
must be accepted.
> And, of course, since
>
>>>> isinstance(True, int)
> True
>
> this code accepts booleans. Oh, but wait, that's by design :-)
Naturally :-)
If you wanted to avoid it, that's easy, add a clause:
if isinstance(obj, bool):
raise TypeError
at the start of the function.
--
Steven
More information about the Python-list
mailing list