Python Forum

Full Version: using a try/except in a conditional expression
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
i needed to make a conditional expression that included testing if a file exists. so i wrote a small function to call os.lstat() in a try/except returning True or False. then i call that function in the expression.

i want to generalize this so what is to be done is passed to a generalized function in the call arguments so i don't need to create a function for each different one of these i might need to include in a boolean expression. does anything like this already exist?

i'm thinking of passing lists of strings with code to exec(), the 1st for lines under try: and the others for the exceptions to handle and their code lines. this would be put together somehow. since i can't do returns in exec() i will need to think up a good design for having the caller specify what and where to return.
If usage case is to write data to a file, but only if it doesn’t already exist then 'x' can be used (from Python Cookbook 3rd edition by Brian K. Jones and David Beazley) :

>>> with open('somefile', 'wt') as f:
...     f.write('Hello\n')
...
>>> with open('somefile', 'xt') as f:
...     f.write('Hello\n')
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileExistsError: [Errno 17] File exists: 'somefile'
If the file is binary mode, use mode xb instead of xt.

One can easily catch FileExistsError with try..except.
(Aug-13-2019, 02:46 AM)Skaperen Wrote: [ -> ]i'm thinking of passing lists of strings with code to exec()

Why would you do that instead of just passing functions? The idea of higher order functions (i.e. functions that take/return functions) is a very useful one and since functions are first class in Python, it's possible to write them.
you guys focused on an example and solved one specific case instead of the general problem.
I'm confused. I thought the general case was you had a structure (try and except) and wanted to parameterise what happens inside that structure. A higher order function lets you do exactly that. If that isn't what you want to do, please explain.
the specific example case is a function that tests for existence of a file under try so the caller does not get an exception. the general case is a function that can do any test the caller requests and do it under try. the issue will be how the general case would be implemented to get that request and carry it out.
It still sounds like passing in the test by means of a function does exactly what you want. For example:

>>> def is_valid(f):
...     try:
...             return f()
...     except:
...             return False
... 
>>> def always_true():
...     return True
... 
>>> def always_throws():
...     raise Exception()
... 
>>> is_valid(always_true)
True
>>> is_valid(always_throws)
False
>>> 
(I didn't have the time to come up with a less contrived example, but hopefully you get the idea).
since the goal is to do it all in the conditional, passing the function means using lambda. but i would have to define and pass it. i guess that's what lambda is good for. how would the data be passed? would you mimic a call by having () right after the lambda?
You can use either a lambda or a named function really. Remember that lambdas can only contain a single expression, so if you need statements or anything else that's more complex, you'll need to use a named function.

As for passing data, both named functions and lambdas can use variables from the enclosing scope. I'm not too big of a fan of that, because I think it can result in code that's difficult to read really. I'd prefer to write a function that takes the data via its parameters and then use partial application to return a new function with fewer arguments that can fit the signature of the function you need to pass.

Consider the following: map applies a function to each item in an iterable, returning a new iterable. Clearly, the function you pass to map needs to take a single argument (since it operates on an item in the iterable). Let's say, for the sake of argument, that I have a list of numbers and I want to add some value n to each item, where that value comes from a user or something. The operator module contains a function add that takes two arguments and returns their sum. With partial, I can use this function and the value n to produce a new function that takes a single argument and adds n to it:

>>> from functools import partial
>>> from operator import add
>>> n = 4
>>> l = [1, 2, 3]
>>> add_n = partial(add, n)
>>> add_n(1)
5
>>> list(map(add_n, l))
[5, 6, 7]
>>> 
Of course, since a lambda is just a function, yes, you need parens to call it.
what i was trying to think through was finding a way to write an expression and pass it to a function to be evaluated in some context to be determined. somehow, evaluating it in the function would be different, such as in a try/except or in a loop or in a conditional or with variables changed by the function, instead of the usual evaluation in the caller's context and passing the value.