For example, I have an object x
that might be None
or a string representation of a float. I want to do the following:
do_stuff_with(float(x) if x else None)
Except without having to type x
twice, as with Ruby's andand library:
require 'andand'
do_stuff_with(x.andand.to_f)
We don't have one of those but it isn't hard to roll your own:
def andand(x, func):
return func(x) if x else None
>>> x = '10.25'
>>> andand(x, float)
10.25
>>> x = None
>>> andand(x, float) is None
True
Taking off on Raymond's idea, here's a factory for making conditional wrappers of this sort. Why write 'em yourself when you can have Python write 'em for you?
def makeandand(func):
return lambda x: func(x) if x else None
andandfloat = makeandand(float)
andandfloat('10.25')
>>> 10.25
andandfloat('')
>>> None
andand
isn't exactly Pythonic, but I'm at a loss for a better name. Maybe trap
since you're trapping the invalid value.
It's worth noting that a common Python idiom is to go ahead and try to do what you need to do, and deal with exceptions as they come along. This is called EAFP, from the maxim "it's Easier to Ask Forgiveness than Permission." So maybe a more Pythonic way to write that is:
def maketrap(func, *exceptions):
def trap(x):
try:
return func(x)
except exceptions or (Exception,):
return None
return andand
trapfloat = maketrap(float)
# optionally specify the exceptions to convert to a None return
# (default is to catch anything but you may want to allow some through)
trapfloat = maketrap(float, ValueError)
trapfloat = maketrap(float, ValueError, TypeError)
# if you don't want to store it (i.e. you only need it once or twice)...
maketrap(float)(x) # ... just call it immediately
In your use case, I think this approach is a win: it transparently deals with anything that can be converted to a float
, and does "the right thing" if a falsy-but-convertible-to-float
value (such as 0) is passed in.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With