UberJumper
UberJumper

Reputation: 21155

Using list comprehensions and exceptions?

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

Answers (7)

Chris
Chris

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

Allie Fitter
Allie Fitter

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

nosklo
nosklo

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

mattkemp
mattkemp

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

nosklo
nosklo

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

Miles
Miles

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

Laurence Gonsalves
Laurence Gonsalves

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

Related Questions