[Tutor] Why begin a function name with an underscore

Steven D'Aprano steve at pearwood.info
Thu Aug 30 04:31:46 CEST 2012


On 30/08/12 05:39, Japhy Bartlett wrote:

> If you tried to check in code like this:
>
> def _validate_int(obj):
>>>       """Raise an exception if obj is not an integer."""
>>>       m = int(obj + 0)  # May raise TypeError.
>>>       if obj != m:
>>>           raise ValueError('expected an integer but got %r' % obj)
>>>
>>>
> we would pat you on your head and be sure to review all of your work very
> closely.

That's a very good idea. You might learn something, and become better
Python programmers who write robust, correct code. Because the advice you
give here in this email makes at least two rookie mistakes. Pay attention
now sonny, Grandpa is going to teach you the right way to suck eggs.


> If nothing else, it's a _very_ verbose way of checking that
> something is an int. If something's meant to be an int, cast it to an int.

It doesn't check if something is an int. It checks if it is an integer. Do
you understand the difference? Richard does, and he's just learning.

Rookie mistake #1: casting to int works on strings, and I don't want to
allow strings as valid arguments. This isn't Perl or PHP where strings
that look like numbers are implicitly treated as numbers.

If you call int on input arguments as a way of telling whether or not you
have been passed an int, your code is buggy.


> If it's garbage it will throw an error - you don't need to invent your
> own messaging.

I don't exactly understand what you mean by "invent your own messaging".
I'm not inventing any messaging -- I use the stock-standard Python
exception mechanism.


> If
>you're worried about rounding, something like `assert int(x) == x` will do
> nicely.

Rookie mistake #2: it certainly will not.

assert is not guaranteed to run. If you use assert to validate input
arguments, your code is buggy because assertions can be disabled at runtime.
Your code will then run without input validation.

If you intend to validate your inputs, and use assert to do so, your code
is buggy.


>> That's probably true, but especially for library code, that's not always
>> the case. I'm merely following the usual best-practice of Python code (to
>> the best of my ability), as seen in the standard library:
>>
>>
> The person asking for help is not writing library code. They're trying to
> learn python, and being pedantic about "best-practice" is not particularly
> helpful, imho.

That is the most ridiculously stupid thing I've seen for a long, long time.
What do you think we should be teaching people? Do you think that beginners
shouldn't learn how to write good quality, robust, bug-free code?

Regardless of whether Richard wants to write library code or not, the code
you are trying to sneer at *is* library code. Richard is trying to understand
why it does what it does. In four sentences:

1) I check input data so my functions detect bad data up front instead of
    silently failing with the wrong result.

2) I intend to accept arbitrary numeric types, not just ints, so long as they
    are integer valued. (Although in hindsight, I'm not sure that's the right
    decision.)

3) I put that check in a function so that if I need to correct a bug, I
    only have to correct it in one place, not ten or twenty.

4) And I make it a private function because it is not part of my library's
    core API, and I want the freedom to remove or replace the function if
    I find a better or different way to do it.



-- 
Steven


More information about the Tutor mailing list