Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #85858 > unrolled thread
| Started by | Jason Friedman <jsf80238@gmail.com> |
|---|---|
| First post | 2015-02-18 21:44 -0700 |
| Last post | 2015-02-19 23:18 -0800 |
| Articles | 12 — 5 participants |
Back to article view | Back to comp.lang.python
What behavior would you expect? Jason Friedman <jsf80238@gmail.com> - 2015-02-18 21:44 -0700
Re: What behavior would you expect? Denis McMahon <denismfmcmahon@gmail.com> - 2015-02-19 14:16 +0000
Re: What behavior would you expect? Chris Angelico <rosuav@gmail.com> - 2015-02-20 02:08 +1100
Re: What behavior would you expect? Denis McMahon <denismfmcmahon@gmail.com> - 2015-02-19 20:03 +0000
Re: What behavior would you expect? Chris Angelico <rosuav@gmail.com> - 2015-02-20 07:11 +1100
Re: What behavior would you expect? Dan Sommers <dan@tombstonezero.net> - 2015-02-20 04:54 +0000
Re: What behavior would you expect? Chris Angelico <rosuav@gmail.com> - 2015-02-20 16:16 +1100
Re: What behavior would you expect? Dan Sommers <dan@tombstonezero.net> - 2015-02-20 05:40 +0000
Re: What behavior would you expect? Jason Friedman <jsf80238@gmail.com> - 2015-02-19 22:49 -0700
Re: What behavior would you expect? Paul Rubin <no.email@nospam.invalid> - 2015-02-19 22:18 -0800
Re: What behavior would you expect? Chris Angelico <rosuav@gmail.com> - 2015-02-20 17:21 +1100
Re: What behavior would you expect? Paul Rubin <no.email@nospam.invalid> - 2015-02-19 23:18 -0800
| From | Jason Friedman <jsf80238@gmail.com> |
|---|---|
| Date | 2015-02-18 21:44 -0700 |
| Subject | What behavior would you expect? |
| Message-ID | <mailman.18856.1424321059.18130.python-list@python.org> |
[Multipart message — attachments visible in raw view] — view raw
I have need to search a directory and return the name of the most recent
file matching a given pattern. Given a directory with these files and
timestamps,
q.pattern1.abc Feb 13
r.pattern1.cdf Feb 12
s.pattern1.efg Feb 10
t.pattern2.abc Feb 13
u.pattern2.xyz Feb 14
v.pattern2.efg Feb 10
calling my_function("/path/to/dir", "pattern1") will return q.pattern1.abc
and calling my_function("/path/to/dir", "pattern2") will return
u.pattern2.xyz.
My question is, what would be a reasonable behavior/result/return value if:
1. "/path/to/dir" does not exist or is not readable
2. no files match the given pattern
Also, what would be a reasonable name for such a function?
[toc] | [next] | [standalone]
| From | Denis McMahon <denismfmcmahon@gmail.com> |
|---|---|
| Date | 2015-02-19 14:16 +0000 |
| Message-ID | <mc4r7v$cm7$2@dont-email.me> |
| In reply to | #85858 |
On Wed, 18 Feb 2015 21:44:12 -0700, Jason Friedman wrote: > My question is, what would be a reasonable behavior/result/return value > if: > 1. "/path/to/dir" does not exist or is not readable Normally I'd say raise an exception. Whether you choose to use an existing exception (will trying to read a non existent dir raise one anyway?) or define your own is up to you. This condition would probably indicate an error in the data received by the function - you should be given a readable directory. If (and only if) being called with an invalid directory is potentially valid, then you could respond to (1) the same as to (2). > 2. no files match the given pattern Return either None, 0, False or an empty string. In both cases, it is then a matter for the calling code to catch the exception or handle the return value appropriately. -- Denis McMahon, denismfmcmahon@gmail.com
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-02-20 02:08 +1100 |
| Message-ID | <mailman.18884.1424358984.18130.python-list@python.org> |
| In reply to | #85904 |
On Fri, Feb 20, 2015 at 1:16 AM, Denis McMahon <denismfmcmahon@gmail.com> wrote:
>> 2. no files match the given pattern
>
> Return either None, 0, False or an empty string.
>
> In both cases, it is then a matter for the calling code to catch the
> exception or handle the return value appropriately.
I'd avoid the empty string here, because "absence of file" should be
very different from "first file matching pattern". Imagine this naive
code:
fn = my_function("/path/to/dir", "pattern2")
move_to("/path/to/dir/" + fn, "/other/path")
In the failure case (nothing matches the pattern), what could happen?
Best is it raises an exception, which would come from the my_function
line. Next best, it returns None, 0, or False, and you get a TypeError
on the deletion, and can trace your way back up. Worst, it returns ""
and oops, you just moved the whole directory into the target, instead
of just one file.
Of course, non-naive code probably prefers a None/0/False return to a
raised exception, but in any case, the difference between those two
options is fairly small. But I'd avoid the potential confusion with
the empty string.
Anyway, that's just API bike-shedding :)
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Denis McMahon <denismfmcmahon@gmail.com> |
|---|---|
| Date | 2015-02-19 20:03 +0000 |
| Message-ID | <mc5fiq$a3f$3@dont-email.me> |
| In reply to | #85906 |
On Fri, 20 Feb 2015 02:08:49 +1100, Chris Angelico wrote: > On Fri, Feb 20, 2015 at 1:16 AM, Denis McMahon > <denismfmcmahon@gmail.com> > wrote: >>> 2. no files match the given pattern >> >> Return either None, 0, False or an empty string. >> >> In both cases, it is then a matter for the calling code to catch the >> exception or handle the return value appropriately. > > I'd avoid the empty string here, because "absence of file" should be > very different from "first file matching pattern". Imagine this naive > code: If your function documentation states that a failure to match any existing file returns an empty string (and if that's the case, then the documentation should do), then whoever calls the function should check the return value isn't an empty string. There's two conflicting "paradigms" as it were here. On the one hand, the return type of a function (when it returns, rather than raising an exception) should be consistent to itself, even if using a language where types are not declared. On the other hand, a failure condition should clearly be a failure condition, which for a language that supports untyped functions means that we have the luxury of being able to return None / Nul[l] / NaN / False / 0 etc instead of a string / object / array / list / dictionary / mapping etc instead of raising an exception for the failure, and so we can try and handle the failure at the calling level without worrying about trapping exceptions. I guess at the end of the day the programmer has to consider and determine which is most appropriate to his application, given the case. As an aside, it's always a good idea to check that what you get looks like what you expected, whether it comes from a function call or as a data packet over the internet, before you start using it to do other things. ;) -- Denis McMahon, denismfmcmahon@gmail.com
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-02-20 07:11 +1100 |
| Message-ID | <mailman.18902.1424376675.18130.python-list@python.org> |
| In reply to | #85928 |
On Fri, Feb 20, 2015 at 7:03 AM, Denis McMahon <denismfmcmahon@gmail.com> wrote: > On the one hand, the return type of a function (when it returns, rather > than raising an exception) should be consistent to itself, even if using > a language where types are not declared. > Yes, so I'd advise against having a function sometimes return a string and sometimes a dict. Sure. But None gets a bit of a special pass here; in a lot of languages, what you'd have is a "nullable" type (eg in C you might declare the return value as "pointer to char", and either return a pointer to a string, or NULL), but in Python, you return None for the special case. So in a sense, "str or None" is not so inconsistent. > I guess at the end of the day the programmer has to consider and > determine which is most appropriate to his application, given the case. Indeed. But knowing that your caller quite possibly won't check, what would you do, to increase the chances of the unexpected being noticed? Again, it comes down to expectations. If 25% of queries are going to return "nothing found", then having that be the empty string is fine - you can be pretty sure your users will test for it. But if that's an extremely rare case, then it may be worth raising an exception instead, so it's safe even if someone forgets to test for the unusual. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Dan Sommers <dan@tombstonezero.net> |
|---|---|
| Date | 2015-02-20 04:54 +0000 |
| Message-ID | <mc6emp$j1q$1@dont-email.me> |
| In reply to | #85929 |
On Fri, 20 Feb 2015 07:11:13 +1100, Chris Angelico wrote: > On Fri, Feb 20, 2015 at 7:03 AM, Denis McMahon <denismfmcmahon@gmail.com> wrote: >> On the one hand, the return type of a function (when it returns, >> rather than raising an exception) should be consistent to itself, >> even if using a language where types are not declared. > > Yes, so I'd advise against having a function sometimes return a string > and sometimes a dict. Sure. But None gets a bit of a special pass > here; in a lot of languages, what you'd have is a "nullable" type (eg > in C you might declare the return value as "pointer to char", and > either return a pointer to a string, or NULL), but in Python, you > return None for the special case. So in a sense, "str or None" is not > so inconsistent. I'm an old C and assembly language programmer, but the older I get, the less I use null (in C or in Java), None (in Python), or equivalent in other languages. If a function can't perform its side effect (like renaming a file), then raise an exception. If a function called for its value can't return that value, then raise an exception; if there are no values to return, then return an empty collection. How much code do we write and read that checks for null (or None, or whatever), and how much time do we spend writing it and reading it? Readability counts. Simple is better than complex. Explicit is better than implicit. Errors should never pass silently. In the face of ambiguity, refuse the temptation to guess. (Wow! I knew I could turn to the Zen for support, but I didn't realize just how much support I would get!) See also <http://en.wikipedia.org/wiki/Void_safety>. Dan
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-02-20 16:16 +1100 |
| Message-ID | <mailman.18908.1424409419.18130.python-list@python.org> |
| In reply to | #85943 |
On Fri, Feb 20, 2015 at 3:54 PM, Dan Sommers <dan@tombstonezero.net> wrote: > if there are no > values to return, then return an empty collection. That one makes sense only if you were going to return a collection anyway, though. If you were going to return a string, returning an empty list on failure makes no sense. Hence the notion of returning a "non-string". ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Dan Sommers <dan@tombstonezero.net> |
|---|---|
| Date | 2015-02-20 05:40 +0000 |
| Message-ID | <mc6hd4$j1q$2@dont-email.me> |
| In reply to | #85945 |
On Fri, 20 Feb 2015 16:16:50 +1100, Chris Angelico wrote: > On Fri, Feb 20, 2015 at 3:54 PM, Dan Sommers <dan@tombstonezero.net> wrote: >> if there are no >> values to return, then return an empty collection. > > That one makes sense only if you were going to return a collection > anyway, though. If you were going to return a string, returning an > empty list on failure makes no sense. Hence the notion of returning a > "non-string". I think I came in a little late, and saw "2. no files match the given pattern," in which case I'm sticking to my story and returning an empty list. The original problem was "to search a directory and return the name of the most recent file matching a given pattern." I'd still prefer an exception to None, and we agree on that an empty string is bad because it's not a non-string and it could be too easily mistaken for a filename.
[toc] | [prev] | [next] | [standalone]
| From | Jason Friedman <jsf80238@gmail.com> |
|---|---|
| Date | 2015-02-19 22:49 -0700 |
| Message-ID | <mailman.18911.1424411363.18130.python-list@python.org> |
| In reply to | #85948 |
[Multipart message — attachments visible in raw view] — view raw
I think I came in a little late, and saw "2. no files match the given > pattern," in which case I'm sticking to my story and returning an empty > list. > > The original problem was "to search a directory and return the name of > the most recent file matching a given pattern." I'd still prefer an > exception to None, and we agree on that an empty string is bad because > it's not a non-string and it could be too easily mistaken for a > filename. > > Agreed.
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2015-02-19 22:18 -0800 |
| Message-ID | <87r3tlds2l.fsf@jester.gateway.pace.com> |
| In reply to | #85948 |
Dan Sommers <dan@tombstonezero.net> writes: > I'd still prefer an exception to None, and we agree on that an empty > string is bad because it's not a non-string and it could be too easily > mistaken for a filename. Empty string would be bad. Sometimes I like to simulate an option type, by returning the value as a 1-element list if there's a value, otherwise as an empty list. So you could say filename = get_filename(...)[0] if you want an exception in the failure case, or you could do something like fs = get_filename(...) if len(fs) == 0: ... # didn't get a filename
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-02-20 17:21 +1100 |
| Message-ID | <mailman.18914.1424413711.18130.python-list@python.org> |
| In reply to | #85953 |
On Fri, Feb 20, 2015 at 5:18 PM, Paul Rubin <no.email@nospam.invalid> wrote: > Empty string would be bad. Sometimes I like to simulate an option type, > by returning the value as a 1-element list if there's a value, otherwise > as an empty list. So you could say > > filename = get_filename(...)[0] > > if you want an exception in the failure case, or you could do something > like > > fs = get_filename(...) > if len(fs) == 0: ... # didn't get a filename Bikeshedding: That could be written as simply "if not fs". :) ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2015-02-19 23:18 -0800 |
| Message-ID | <87mw49dpar.fsf@jester.gateway.pace.com> |
| In reply to | #85954 |
Chris Angelico <rosuav@gmail.com> writes: >> if len(fs) == 0: ... # didn't get a filename > Bikeshedding: That could be written as simply "if not fs". :) Yeah, in that instance you could do that. It's an unsafe practice when None is used as the no-value marker, since the empty string is a perfectly good string and also converts to boolean false.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web