Reputation: 21155
Okay lets say I have a list, and I want to check if that list exists within another list. I can do that doing this:
all(value in some_map for value in required_values)
Which works fine, but lets say I want to the raise an exception when a required value is missing, with the value that it is missing. How can I do that using list comprehension?
I'm more or less curious, all signs seem to point to no.
EDIT Argh I meant this:
for value in required_values:
if value not in some_map:
raise somecustomException(value)
Looking at those I cant see how I can find the value where the error occurred
Upvotes: 4
Views: 2572
Reputation: 1623
You can certainly hack something together, but it is not particularly readable.
(_ for _ in ())
defines a generator, from which you can use the throw
method to raise any exception you want.
all((_ for _ in ()).throw(somecustomException(value)) for value in required_values if value not in some_map)
That said, readability aside, it doesn't make sense to use a list comprehension unless you're actually going to use the list. This might make more sense as something like:
map_values=[some_map[value] if value in some_map else (_ for _ in ()).throw(somecustomException(value)) for value in required_values]
But even then it probably makes more sense to handle the exception outside the loop. If you want to raise a custom exception for some reason you can just catch the KeyError and raise your own exception.
try:
found_values=[some_map[value] for value in required_values]
except KeyError as e:
raise somecustomException(e.args[0])
Upvotes: 0
Reputation: 1807
I was wondering about tonight. My use case is iterating over a list of objects and raising an error when the object was not of a specific type. My solution is to use a generator.
def iter_my_class(my_class_list):
for c in my_class_list:
if not isinstance(c, MyClass):
raise ValueError('Expected MyClass')
yield c
Then used as
classes = [c for c in iter_my_class(my_class_list)]
I wrote this on my phone. If that runs without errors you all owe me a beer.
Upvotes: 0
Reputation: 223062
If you don't want to consider duplicates and the values are hashable, use sets. They're easier, faster, and can extract "all" elements missing in a single operation:
required_values = set('abc') # store this as a set from the beginning
values = set('ab')
missing = required_values - values
if missing:
raise SomeException('The values %r are not in %r' %
(missing, required_values))
Upvotes: 2
Reputation: 363
While I think using sets (like nosklo's example) is better, you could do something simple like this:
def has_required(some_map, value):
if not value in some_map:
raise RequiredException('Missing required value: %s' % value)
all(has_required(some_map, value) for value in required_values)
Upvotes: -2
Reputation: 223062
Another (ugly) possibility would be the error_on_false
function:
def error_on_false(value)
if value:
return value
else:
raise Exception('Wrong value: %r' % value)
if all(error_on_false(value in some_map) for value in required_values):
continue_code()
do_something('...')
That's ugly. I'd use the set
instead.
Upvotes: 0
Reputation: 32478
lets say i want to the raise an exception when a required value is missing, with the value that it is missing. How can i do that using list comprehension?
List comprehensions are a syntactically concise way to create a list based on some existing list—they're not a general-purpose way of writing any for
-loop in a single line. In this example, you're not actually creating a list, so it doesn't make any sense to use a list comprehension.
Upvotes: 14
Reputation: 143304
You can't use raise in a list comprehension. You can check for yourself by looking at the grammar in the Python Language Reference.
You can however, invoke a function which raises an exception for you.
Upvotes: 2