17

I need to check if more than one of a, b, c, and d are being defined:

def myfunction(input, a=False, b=False, c=False, d=False):
    if <more than one True> in a, b, c, d:
    print("Please specify only one of 'a', 'b', 'c', 'd'.)

I am currently nesting if statements, but that looks horrid. Could you suggest anything better?

TheChymera
  • 17,004
  • 14
  • 56
  • 86
  • 2
    Perhaps a different function signature is in order. If the user is allowed to make exactly one choice, how about `def myfunction(input, choice)`, where `choice` is one of "a", "b", "c", "d"? – Kevin Nov 17 '14 at 15:29
  • `def multiple_true(*args):it = iter(args);return any(it) and any(it)` Usage: `if multiple_true(a, b, c, d): ...` – Steven Rumbalski Nov 17 '14 at 15:36
  • @Martijn Pieters - where is the duplicate? – TheChymera Nov 18 '14 at 05:32
  • @TheChymera you are testing the inverse to return an error message; the other tests if exactly one is true. – Martijn Pieters Nov 18 '14 at 08:02
  • Yeah, I don't think the inverse counts as a duplicate. Also, it's not even just the inverse, the title implies he is testing for one or two. As you can plainly see, the answers below do not closely resemble the answers he got. – TheChymera Nov 19 '14 at 22:25

3 Answers3

20

Try adding the values:

if sum([a,b,c,d]) > 1:
    print("Please specify at most one of 'a', 'b', 'c', 'd'.")

This works because boolean values inherit from int, but it could be subject to abuse if someone passed integers. If that is a risk cast them all to booleans:

if sum(map(bool, [a,b,c,d])) > 1:
    print("Please specify at most one of 'a', 'b', 'c', 'd'.")

Or if you want exactly one flag to be True:

if sum(map(bool, [a,b,c,d])) != 1:
    print("Please specify exactly one of 'a', 'b', 'c', 'd'.")
Duncan
  • 92,073
  • 11
  • 122
  • 156
19

First thing that comes to mind:

if [a, b, c, d].count(True) > 1:
Rusty
  • 904
  • 4
  • 10
  • 1
    I *think* at PyCon 2014 a speaker said this is the right way to check this and explicitly said sum was the wrong way. I recall it was someone well respected. I wish I remembered specifics – Charles L. Apr 17 '20 at 17:05
3

If you want exactly 1 True value:

 def myfunction(input, a=False, b=False, c=False, d=False):
    if filter(None,[a, b, c, d]) != [True]:
        print("Please specify only one of 'a', 'b', 'c', 'd'.)")
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321