Allow only one keyword that is not "None" in **kwargs

Question:

I would like to explain my problem with an example.
(The example I gave may not make much sense in itself, but I thought it would be better understood this way.)

def animal(*args, **kwargs):
    duck = kwargs.get("duck")
    lion = kwargs.get("lion")
    wolf = kwargs.get("wolf")
    # bear, fish, bee etc...
    
    
    if duck:
        if lion or wolf:
            raise ValueError("When 'duck' is specified, you cannot value other arguments.")
        print(f"Duck: {duck}!")
    elif lion:
        if duck or wolf:
            raise ValueError("When 'lion' is specified, you cannot value other arguments.")
        print(f"Lion: {lion}!")
    elif wolf:
        if duck or lion:
            raise ValueError("When 'wolf' is specified, you cannot value other arguments.")
        print(f"Wolf: {wolf}!")
    
    # other stuff ...

animal()  # ✓
animal(duck="quack")  # ✓
animal(duck="quack", lion=None)  # ✓
animal(duck="quack", lion="roar")  # X

As the arguments increase, the amount of "or" also increases. Is there a better way to achieve same result?

Asked By: Mustafa AHCI

||

Answers:

As others have commented, you can count the number of non-None values in kwargs, and raise an exception if that number is greater than one.

x = 0
for val in kwargs.values():
    if val is not None:
        x += 1
    if x > 1:
        raise ValueError("Too many values present")
Answered By: John Gordon
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.