On 24Oct2014 15:50, Ben Finney <ben+pyt...@benfinney.id.au> wrote:
Is this a hurdle for newcomers? Yes, and that's why the standard library
API documentation is not a tutorial. We have separate tutorial
documentation for that.

It's not a problem with the documentation of ‘signal.getsignal’ that it
doesn't have an exhaustive list of all exception classes that might be
raised. This is Python, not Java; [...]

Further to this, in particular WRT to Java and other strongly typed static languages, in Java one must define what exceptions a function may throw or the code won't even compile. This is just great in one sense: it lets you write interface definitions with complete confidence about the types of failure the caller must accomodate.

However, this only works rigorously because the same information is available on everything the function itself calls, courtesy of the same requirements and the staticly typed nature of the language.

With Python, this goes out the window. Because _names_ are untyped (they may be bound to any object) you can't make the same guarentees. Newcomers will find this disorienting; I did.

Because of this, not only can't one document everything a function might throw, one can return to writing relevant documents that says what a function does, what it expected to receive, and specific exceptions representing important failure modes special to the operation. Pass it something else, and undocumented badness may ensue (GIGO).

One thing the newcomer should keep in mind is that with library wrapper functions (such as almost everything in the "os" module), the python documentation says what the function does and what underlying library function is involved; detailed failure modes often are to be found in the external library documentation.

exceptions are used prolifically as a
flow control method, for code to let its call stack know something
unusual occurred.

This, again, is surprising to newcomers, who will often think of exceptions only in "something went wrong" scenarios.

Raising an exception, particularly StopIteration from iterators, frees one from choosing a sentinel value for every single function to indicate some value not in the legitimate domain.

Consider an "iteration" in C where the values from from an external call. It might naturally be written like this:

  while ( (value=function(....)) != -1) {
    loop body here...
  }

Here, "-1" is a sentinel value returned by function() when there are no more values for the iteration. It needs to be some naturally "invalid" return value, and in C is often -1 for intergers and NULL for pointers including strings. Regardless, a special value needs to be chosen and exposed in the loop condition.

Comared with almost every Python iteration loop:

  for value in generator_function():
    loop body here...

Here the generator (usually automaticly) raises StopIteration, and the Python "for" loop implementation automatically catches that exception and exits the loop. No sentinel values required.

Again with sentinel values, for non-iteration: Compare with, say, POSIX system calls in C. They mostly return -1 on error, and every piece of code calling them has to look like this:

  if (unlink(some_pathname) == -1) {
    consult errno, recover or complain, maybe return or abort, etc ...
  else:
    ... continue after successful operation...

With exceptions one can often write clumps of operations all of which success without explicit checking verbiage:

  os.unlink(some_pathname)
  os.rename(this, that)

because a failed operation will raise an exception.

Cheers,
Cameron Simpson <c...@zip.com.au>

Mike was a sportbike rider, He'd say "El grande numero one!"
With a 'No Fear' sticker on his zx11, he'd lightem'up just for fun...
        - Mike Hardcore DoD#5010 <mo...@netcom.com>
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to