Question

When you want to print a bunch of variables in Python, you have quite a few options, such as:

for i in range(len(iterable)):
    print iterable[i].name

OR

map(lambda i: sys.stdout.write(i.name), iterable)

The reason I use sys.stdout.write instead of print in the second example is that lambdas won't accept print, but sys.stdout.write serves the same purpose.

You can also print conditionally with the ternary operator:

map(lambda n: None if n % 2 else sys.stdout.write(str(n)), range(1, 100))

So it would be really handy if I could check an entire sequence for a condition that would warrant an exception in such a way:

map(lambda o: raise InvalidObjectError, o.name if not o.isValid else o(), iterable)

But that doesn't work. Is there such an object for raise in Python, and if so, where is it?

Was it helpful?

Solution

There is no Python "object" (built-in or in the standard library) for raise, you have to build one yourself (typical short snippet that goes in one's util.py...!):

def do_raise(exc): raise exc

typically to be called as do_raise(InvalidObjectError(o.name)).

OTHER TIPS

I don't think it's possible to use raise in a lambda, like you're attempting to do. raise is a statement/expression, not an object. As @Alex Martelli has stated, you'd likely need to define a function to do the check for you. Now, the function could be declared locally, within the same context.

As far as the exception types, which is what your question seems to be aimed at: Exception types are not defined automatically. For simple exception types, where you either want just a text message, or none at all, typically exception types are defined simply at your module/file scope as:

class InvalidObjectError(Exception): pass

Do. Not. Do. This.

This is a dreadful idea.

map(lambda o: raise InvalidObjectError, o.name if not o.isValid else o(), iterable)

Do this.

class SomeValidatingClass( object ):
    def isValid( self ):
        try: 
            self.validate()
        except InvalidObjectError:
            return False
        return True
    def validate( self ):
        """raises InvalidObjectErorr if there's a problem."""

[ x.validate() for x in iterable ]

No map. No lambda. Same behavior.

For your first example I use form like this:

print '\n'.join(obj.name for obj in iterable)

Also I would use:

firstnotvalid = next(obj.name for obj in iterable if not obj.is_valid())

And instead of:

>>> import sys
>>> map(lambda n: None if n % 2 else sys.stdout.write(str(n)), range(1, 100))
2468101214161820222426283032343638404244464850525456586062646668707274767880828486889092949698[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]

I would do:

>>> print (', '.join(str(number) for number in range(1,100) if not number % 2))
2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98

Ignoring that there is step parameter for range, as I think the function is simplification of other more complicated functions.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top