3

I'm tryng to learn different ways to do simple things in python, while also learning a bit about some functional practices. I have some numbers that the user inputs, and I want to know if they really are numbers. I've come up with this kind of classic solution:

def foo(list_of_inputs):
    for n in list_of_inputs:
       if not hasattr(n, "real"):
           # some number is not a number!
           return False
    # all are numbers
    return True

But then, I figured out this other "thing" that may have some potential:

def foo(list_of_inputs):
    bool_list = map(lambda input: hasattr(input, "real"), list_of_inputs)
    return reduce(lambda x, y: x == y, bool_list)

I think that maybe a function that returns "True" if all members of a collection, iterable, or whatever the correct concept I'm looking for, are "True", may already be something somewhat common, and also, this second attempt doesn't return when a "False" is found, while the classic one does... But I find it elegant, and maybe that is because I'm not there yet with programming in general.

So my question is: what's the "probably better" way to do this?

ferhtgoldaraz
  • 1,693
  • 3
  • 15
  • 20

2 Answers2

3

As mentioned, the all function will do what you want. What you describe you're trying to do can also be done with the str.isnumeric() function.

def foo(listOfInputs):
    return all(map(str.isnumeric,listOfInputs))

Edit: I'm finding that it fails on ['1','2','3.14','4'] which is a little annoying. Maybe someone can come up with a cleverer solution than this, but I decided to wrap a slightly modified approach in a try:

def foo(listOfInputs):
    try:
        return all(map(float,listOfInputs))
    except ValueError:
        return False

That works on:

['1','2','-3','4']
['1','2','3.14','4']
Ali Alkhatib
  • 425
  • 2
  • 8
  • Nice to know about isnumeric(), It wasn't working, but it seems that it is because I'm on python 2.7.5 and it has to be unicode. Thanks a lot. Maybe I should just forget about trying to avoid testing all if unnecesary, at least for now. – ferhtgoldaraz Sep 09 '13 at 01:15
  • Ah my bad. testing user input is a good practice, but you can easily "go down the rabbit hole" checking for any possible thing a user could enter. Example: what if someone enters `1,000,000`? Or `1,199.99`? Or what if they're in Europe and they type `1.000.000,99`? These should all be valid, in theory, but writing code to test all of these could become a whole [regex](http://stackoverflow.com/questions/tagged/regex) thing. – Ali Alkhatib Sep 09 '13 at 01:25
  • Yeah,but hey, there are some syntactic constrains, so maybe the best way to deal with those edge cases is to inform how input is expected. I'm from Europe actually, so I get how the example you mention can be a problem. – ferhtgoldaraz Sep 09 '13 at 01:38
  • 1
    You don't need the lamba in `foo`. `return all(map(str.isnumeric, listOfInputs))` – dietbuddha Sep 09 '13 at 03:04
  • That's really cool, thanks for the tip. I've updated the answer to reflect this. – Ali Alkhatib Sep 09 '13 at 03:20
1

You mean something like the built-in all function?

Return True if all elements of the iterable are true (or if the iterable is empty). Equivalent to:

user2246674
  • 7,621
  • 25
  • 28
  • Yeah, all(map(lambda x: hasattr(x, "real"), list_of_inputs)) looks better, Thanks! I should check the bultins more often... But there's still the thing with checking all instead of returning when any is "False". Thank you though – ferhtgoldaraz Sep 09 '13 at 01:05
  • @ferhtgoldaraz `(map(lambda x: hasattr(x, "real"), list_of_inputs))` looks better than the short and sweet `all`? –  Sep 09 '13 at 01:06
  • No, it's just that I need to build the collection of booleans, and call all() on it... Don't I? – ferhtgoldaraz Sep 09 '13 at 01:24