Bottom Page

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 TO ELSE OR NOT TO ELSE?
#1
Should we always use else statements?

By using else statements you are kind of doing the same thing that the programming gods Ken Thompson and Rob Pike recommend in GOLANG, which is to make sure you ALWAYS handle errors. Since python is dynamically typed, variables can hold stuff that you don't necessarily want.

def check_int(number):
    if type(number) == int:
        return number
    else:
        error_name = "check_int failure"
        error_details = "User did not pass an integer at"
        error_datetime = datetime.now()
        db_engine.execute(f"INSERT INTO log (error, details, datetime) VALUES({error_name}, {error_details}, {error_datetime);")
        return -1

        # or: raise ValueError('A very specific bad thing happened.') if you want runtime to stop?
        # or: render("404.html", details="dude, stop sending us strings homeslice")
I can give an example where this form of logging is important,

Say that I am controlling a remote control airplane with a remote server API.

I would like to know:
  • Is my server receiving the correct client session?
    (we can check it with if else and log whenever someone is hacking/spamming my very important server)

  • Check if my change in altitude is less than some safety measure else send an email to the engineers for quick help.
Quote
#2
I don't think the word "always" should be applied very liberally, and definitely not in this case. Your example definitely doesn't need it, since the if-branch already returns.

This is beside the point, but there's several issues I have with your example.

- You return bad values (-1) if the passed number isn't an int. The meaning you've described the function to have with the first three lines is that you're simply returning an int, which means valid usage would look something like: current_inventory += check_int(received_quantity), which could cause the inventory to decrease just because the user passed bad info?

- The name, itself, check_int(), implies that you're checking for the validity of something. ...which is what True/False is for. Just from looking at the function's signature, I'd guess that the correct usage would be this:
received_quantity = # get something from the user
if check_int(received_quantity):
    current_inventory += received_quantity
Quote
#3
Yep, that function name is very poor :/ that is a good catch.

I really meant to give it another name like def make_decision(number), because what I was wondering was that really good programmers in python never use else statement. However, the creators of Golang did recommend always checking/log for errors, which else statements help you do.
Quote
#4
(Apr-27-2019, 02:04 AM)rxndy Wrote: Should we always use else statements?
Definitely not. The use of else will depend on your use case. I will open a bracket - some recommend always using else, but not in the context you have in mind, but as a way to show that programmer has considered all possible outcomes/did not forget the else (some branch). See this recent discussion https://python-forum.io/Thread-Just-comp...1#pid78691 that touches the topic.

Your examples are mix of input validation/type checking and regular branching. Also each programming language has it patterns (and tools) and one should use these.

As to error handling - would you handle all errors, which errors would you handle and how would you handle them also depends on your use case. For example in a software for end user you would make reasonable effort to handle at least basic errors - for example you don't want user to get error for invalid input. How you would handle it is another question - I would come to that shortly. On other hand if you write a package that would be used by other programmers in their code most probably you would want to propagate the errors so that they handle them themselves the way they want, i.e. you don't want to restrict them with your logging for example (for example think of python wrapper/sdk around some API).

Regarding error handling python has try/except/else/finally so for error handling you would use this construct. Note it has else and finally, but they are optional. This construct has advantage over using if/else especially in cases where race conditions are possible (think of checking that file exists before deleting, but with if/else it can be deleted by some other procees between you check it exists and actually trying to delete it). It's an implementation of python philosophy - Easier to ask for forgiveness than permission (EFAP). See also https://docs.quantifiedcode.com/python-a...files.html

As to type checking - I would say that more often than not type checking is not needed and even discouraged by python community as anti-pattern. That is so called duck typing. And if you really have to do type checking it's recommended to use isinstance() instead of type().

Let's return to your examples. How would you make sure user has supplied integer
def get_int(prompt=''):
    while True:
        user_input = input(prompt)
        try:
            return int(user_input)
        except ValueError:
            # you can log here
            print('This is not a valid input. Please enter an integer')

my_int = get_int('Please enter an integer number: ')
print(f'You have entered {my_int}')
Output:
Please enter an integer number: a This is not a valid input. Please enter an integer Please enter an integer number: This is not a valid input. Please enter an integer Please enter an integer number: 1.2 This is not a valid input. Please enter an integer Please enter an integer number: 5 You have entered 5 >>>
Your other two examples are actually regular branching of your program flow and using else might be warranted depending on what you want to do. Let's look at your last example.
You read some value from a sensor and process it. It's possible to have 3 scenarios:

if reading higher than some value - do A
if value below that value - do B but also send a message/turn on alarm, log, etc. Here B can be also "do nothing"
if value below that value - still do A, but also send a message/turn on alarm/log, etc.

if we have 1 and 2 in pseudo-code you would do

if reading > some_value:
    do A
else:
    do B
    send message/alarm/log, etc.
but in case 1 and 3 you can do

if reading > some_value:
    do A
else:
    do A
    send message/alarm/log, etc.
OR skip the else
if reading <= some_value:
    send message/alarm/log, etc.
do A
in my view the second one is better and I would go for it.

Sorry if my answer may be a little bit chaotic, but it's because in your question you mix a lot of different concepts/paradigms/code patterns
Yoriz likes this post
Quote
#5
Wow, I totally agree with you! I will take those golden nuggets on my next app.

mainly the part about asking for forgiveness instead of checking for permission.
Quote

Top Page

Forum Jump:


Users browsing this thread: 1 Guest(s)