I've written a little function that iterates over two iterables. The first one returns an object which is used to convert an object of the second iterable. I've got a working implementation, but would like to get some feedback.
A simple use case would look like this:
list(serialize([String(), String()], [1, 2])) # should work
list(serialize([String(), String()], range(3))) # should fail, too many values
list(serialize([String(), String()], range(1))) # should fail, too few values
But sometimes the number of values is not known but the type is the same. Therefore infinite iterators should be allowed as types argument:
list(serialize(it.repeat(String()), range(3))) # should work
Of course finite iterators are allowed as well:
list(serialize(it.repeat(String(), times=3), range(3))) # should work
list(serialize(it.repeat(String(), times=4), range(5))) # should fail
# should fail, but probably not that easy to do.
list(serialize(it.repeat(String(), times=4), range(3)))
My working implementation (except for the last case) looks like this:
class String(object):
def dump(self, value):
return str(value)
def serialize(types, values):
class Stop(object):
"""Since None can be valid value we use it as fillvalue."""
if isinstance(types, collections.Sized):
# Since None is a valid value, use a different fillvalue.
tv_pairs = it.izip_longest(types, values, fillvalue=Stop)
else:
tv_pairs = it.izip(it.chain(types, (Stop,)), values)
for type, value in tv_pairs:
if type is Stop:
raise ValueError('Too many values.')
if value is Stop:
raise ValueError('Too few values.')
yield type.dump(value)
izip
? \$\endgroup\$