Reputation: 8947
I want to parse data from a file, and for each line I want to validate each piece of data. Imagine that the first few lines of the file look something like this:
id|date|rate|notes
1|2016-07-23|0.765|foo
2|2016-07-23|0.432|
1|2016-07-24|0.697|bar
I want to make sure that the date
and rate
values are valid, and I have functions that can check that they are. These functions return a value if the input is valid, and throw an error if it's not. E.g:
def validate_date(string):
parts = [int(x) for x in string.split("-")
return datetime.date(*parts)
I don't care about the values of the id
or notes
fields. So I can do this:
validators = dict()
validators['id'] = lambda x: x
validators['date'] = validate_date
validators['rate'] = validate_rate
validators['notes'] = lambda x: x
Then, once I've read in each row (as a dictionary) I can validate each field like so:
output = dict()
for key, value in line.iteritems()
output[key] = validators[key](value)
return output
Which is all great. The problem is that the file I want to parse actually has dozens of fields that I don't care about, and only a handful that I do. So, instead of manually having to define a line like validators['id'] = lambda x: x
, what I'd like to do is use something like a defaultdict
to return a function that simply returns the input. But, if I try:
def do_nothing(x):
return x
foo = defaultdict(do_nothing)
foo['bar'](1)
I get the error: do_nothing() takes exactly 1 argument (0 given)
.
Is there a way to create something that is like a defaultdict
, but that returns an object that can take an argument?
Upvotes: 0
Views: 78
Reputation: 77367
The defaultdict
returns whatever was created by its default function so all you need is for do_nothing
to return a callable that takes one param. You don't really need do_nothing
at all, just
validators = collections.defaultdict(lambda: lambda x: x)
Now defaultdict
returns lambda x: x
which takes one parameter so you can do
validators['foo'](1)
and the lambda is called with 1
.
Upvotes: 3