Python Style Question
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Thu Oct 30 07:10:06 EDT 2014
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__)
load_int() covers the three cases you mention, and raises either ValueError
for malformed strings (e.g. 'x') or TypeError for things which aren't ints
(e.g. floats, dicts, etc.). Any other exception is probably a bug that
needs to be fixed.
Then, to cover case 4), ignoring everything else, you have a choice between
a procedural form:
values = []
for obj in l:
try:
values.append(load_int(obj))
except (ValueError, TypeError):
pass
or a functional form:
def tolerant_load_int(obj, default=None):
try:
return load_int(obj)
except (ValueError, TypeError):
return default
values = [n for n in map(tolerant_load_int, l) if n is not None]
# alternative to using map
values = [n for n in (tolerant_load_int(obj) for obj in l) if n is not None]
--
Steven
More information about the Python-list
mailing list