Ryan is an engineer in the Sacramento Area with a focus in Python, Ruby, and Rust. Bash/Python Exercism mentor. Coding, physics, calculus, music, woodworking. Looking for work!
That's interesting. So far, from what I've seen, raising Exceptions seems like a valid, Pythonic way to handle edge cases.
I'm interested to find out your opinion on how I'd do things normally.
For the division function, it seems like a totally valid way to go to let it raise its own ZeroDivisionError. Looking in log files or seeing that come up in the terminal would be as good a message as any to communicate what's happening. You would see that a function called divide is raising a ZeroDivisionError, and you would know exactly what the problem is and that you need to track down where a zero is getting sent to your divide function.
And leaving it up to client code to handle the propagated ZeroDivisionError is a pretty standard idiom in Python. If you really feel the need to catch the error, you could maybe raise your own signaling the bad input value?
defdivide(first:float,second:float)->float:ifsecond==0:raiseValueError("Zero is an invalid divisor.")returnfirst/second
In fact, Python's documentation itself recommends this idiom in the bisect module docs. If a binary search doesn't find the value it's looking for, it doesn't return None, it raises a ValueError. It's up to the client to handle that exception.
All of that to say, I think the wrapped value idea is neat, and a useful idiom from languages like Go and Rust. I can see that it would definitely have some use cases in Python where it would be the best. I agree that you wouldn't want to lean on Exceptions for standard control flow for the most part.
But using exceptions to indicate a state other than the happy path seems like it's definitely not an anti-pattern in Python, and in a lot of cases, it's the Pythonic way to go.
I like to separate two kind of layers I have in my app: logic and application.
Logic is almost independent, it is my choice how to work with it. It allows a huge portion of freedom.
On the other hand it requires to be readable. Because there are no other-projects-like-this-one. So, that's why it is important for me to make exceptions crystal clear. Other people does not know if my FetchUser class is going to raise or not. And I do want to make this contract explicit.
On the lower, application, level I am using the existing stuff. Like django, celery, scrapy. And I need to respect their APIs. And, for example, django uses a lot of exceptions to control the execution flow. So, I prefer to raise on this level. And check that every exception is meaningful with tests.
That's how I see the big picture. Hope that you will find a proper use-cases for returns!
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
That's interesting. So far, from what I've seen, raising Exceptions seems like a valid, Pythonic way to handle edge cases.
I'm interested to find out your opinion on how I'd do things normally.
For the division function, it seems like a totally valid way to go to let it raise its own
ZeroDivisionError
. Looking in log files or seeing that come up in the terminal would be as good a message as any to communicate what's happening. You would see that a function calleddivide
is raising aZeroDivisionError
, and you would know exactly what the problem is and that you need to track down where a zero is getting sent to your divide function.And leaving it up to client code to handle the propagated ZeroDivisionError is a pretty standard idiom in Python. If you really feel the need to catch the error, you could maybe raise your own signaling the bad input value?
In fact, Python's documentation itself recommends this idiom in the
bisect
module docs. If a binary search doesn't find the value it's looking for, it doesn't return None, it raises a ValueError. It's up to the client to handle that exception.All of that to say, I think the wrapped value idea is neat, and a useful idiom from languages like Go and Rust. I can see that it would definitely have some use cases in Python where it would be the best. I agree that you wouldn't want to lean on Exceptions for standard control flow for the most part.
But using exceptions to indicate a state other than the happy path seems like it's definitely not an anti-pattern in Python, and in a lot of cases, it's the Pythonic way to go.
Does that make sense at all?
I like to separate two kind of layers I have in my app: logic and application.
Logic is almost independent, it is my choice how to work with it. It allows a huge portion of freedom.
On the other hand it requires to be readable. Because there are no other-projects-like-this-one. So, that's why it is important for me to make exceptions crystal clear. Other people does not know if my
FetchUser
class is going to raise or not. And I do want to make this contract explicit.On the lower, application, level I am using the existing stuff. Like
django
,celery
,scrapy
. And I need to respect their APIs. And, for example,django
uses a lot of exceptions to control the execution flow. So, I prefer to raise on this level. And check that every exception is meaningful with tests.That's how I see the big picture. Hope that you will find a proper use-cases for
returns
!