1

Is there a way to improve this code to make it shorter?

if date_a is None and date_b is None and date_c is None: 
    start_date = current_date
else:
    if date_a is not None:
        start_date = date_a
    elif date_b is not None:
        start_date = date_b
    elif date_c is not None:
        start_date = date_c
1
  • start_date = date_a or date_b or date_c or current_date would work, assuming that no possible value of these variables (other than None) is a "falsy" value (zero, empty string, empty container, etc.) Commented Aug 1, 2021 at 22:33

4 Answers 4

2

You can use or, which will give you the first truthy value:

start_date = date_a or date_b or date_c or current_date

Another solution would be to turn them into an iterable, add an is None filter, and pull the first item using next():

start_date = next(date for date in (
    date_a, 
    date_b, 
    date_c, 
    current_date
) if date is not None)

This approach works better if you need a condition other than "truthiness", or if you have a lot of values (in which case organizing them in an iterable container is likely easier than pasting them into a long or sequence).

Sign up to request clarification or add additional context in comments.

Comments

2

As an alternative in Python >= 3.8 you can use an assignment expression plus any():

any(start_date := d for d in (date_a, date_b, date_c, current_date))

In your specific case I suspect that a chain of or would be faster, however any() will also work well if you have a collection of variables and not just single variables with different names:

any(start_date := d for d in dates)

The return value of any will let you know whether there was some truthy value or not.

5 Comments

Nice, no idea this existed.
Interesting. I tested it and I was wondering, why is 'any' required? Why I cannot just do: (start_date := d for d in (date_a, date_b, date_c, current_date))
@Forna because any will stop at the first item that is truthy, while what you wrote will simply go through all the elements and you will always end up with the last one being assigned to start_date after that statement.
IMO any(start_date := d for d in (date_a, date_b, date_c, current_date)) should never pass any sane code review
@juanpa.arrivillaga yeah, I feel like I have to agree there.
1

First, you can remove one if/else depth:

if date_a is not None:
    start_date = date_a
elif date_b is not None:
    start_date = date_b
elif date_c is not None:
    start_date = date_c
else:
    start_date = current_date

You could also take advantage of the for...else statement:

for start_date in (date_a, date_b, date_c):
    if start_date is not None:
        break
else:
    start_date = current_date

The else only happens if none of the break conditions triggered, e.g. if all of the potential start_date's were None.

Comments

0

You can do something like:

start_date = date_a or date_b or date_c or current_date

Alternatively, there really is nothing wrong with:

if date_a is not None:
    start_date = date_a
elif date_b is not None:
    start_date = date_b
elif date_c is not None:
    start_date = date_c
else:
    start_date = current_date

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.