Hi all, the PEP 8 says that function and method names should be lowercase, with words separated by underscores as necessary to improve readability. Maybe it could be a good idea to specify in the PEP8 that the predicates should not be separated by underscores, because it is pretty annoying to see this kind of inconsistency: str.isdigit() float.is_integer() -- Marco Buttu INAF-Osservatorio Astronomico di Cagliari Via della Scienza n. 5, 09047 Selargius (CA) Phone: 070 711 80 217 Email: mbuttu@oa-cagliari.inaf.it
On Feb 05, 2015, at 11:36 PM, Marco Buttu wrote:
Hi all, the PEP 8 says that function and method names should be lowercase, with words separated by underscores as necessary to improve readability. Maybe it could be a good idea to specify in the PEP8 that the predicates should not be separated by underscores, because it is pretty annoying to see this kind of inconsistency:
str.isdigit() float.is_integer()
I don't think PEP 8 should change. Even words in predicates should be separated by an underscore. But it's not worth it to go back and change old APIs that have been in existence forever. Cheers, -Barry
On 06/02/2015 01:12, Barry Warsaw wrote:
On Feb 05, 2015, at 11:36 PM, Marco Buttu wrote:
Hi all, the PEP 8 says that function and method names should be lowercase, with words separated by underscores as necessary to improve readability. Maybe it could be a good idea to specify in the PEP8 that the predicates should not be separated by underscores, because it is pretty annoying to see this kind of inconsistency:
str.isdigit() float.is_integer() I don't think PEP 8 should change. Even words in predicates should be separated by an underscore.
Are you proposing to change our mind? Because currently we have both in the core and in the standard library mainly predicates *not* separated by underscores: isinstance() issubclass() hasattr() str.is* set.is* bytearray.is* math.is* os.is* ... And recently: asyncio.iscoroutinefunction(). Your proposal seems to me really inconsistent with the whole codebase, and I think the reason sometime we get wrong (as in the case of float.is_integer()) is a lack (about predicates) in the PEP8. The PEP8 suggests that we should use "words separated by underscores as necessary to improve readability", and that's why sometimes we write is_foo() instead of isfoo(). I believe your suggestion is an evidence of that lack. So, I am proposing to be more clear, maybe by writing somethink like that: """ Function names should be lowercase and, except for predicates, with words separated by underscores as necessary to improve readability. Yes: # Do not use underscores in predicates isinstance() hasattr() # Use underscores to improve readability dont_write_bytecode() No: is_instance() has_attr() dontwritebytecode() """ We have to change just this part of the PEP8, because the method section says to use the function naming rules.
But it's not worth it to go back and change old APIs that have been in existence forever.
I am not so crazy ;) I am just proposing a clear rule for predicates in order to avoid, _in the future_, inconsistency with the current general rule. -- Marco Buttu INAF-Osservatorio Astronomico di Cagliari Via della Scienza n. 5, 09047 Selargius (CA) Phone: 070 711 80 217 Email: mbuttu@oa-cagliari.inaf.it
On Feb 5, 2015, at 22:21, Marco Buttu
On 06/02/2015 01:12, Barry Warsaw wrote:
On Feb 05, 2015, at 11:36 PM, Marco Buttu wrote:
Hi all, the PEP 8 says that function and method names should be lowercase, with words separated by underscores as necessary to improve readability. Maybe it could be a good idea to specify in the PEP8 that the predicates should not be separated by underscores, because it is pretty annoying to see this kind of inconsistency:
str.isdigit() float.is_integer() I don't think PEP 8 should change. Even words in predicates should be separated by an underscore.
Are you proposing to change our mind? Because currently we have both in the core and in the standard library mainly predicates *not* separated by underscores:
isinstance() issubclass() hasattr() str.is* set.is* bytearray.is* math.is* os.is* ...
And recently: asyncio.iscoroutinefunction(). Your proposal seems to me really inconsistent with the whole codebase,
The PEP already says, right in the existing sentence you quoted, "as necessary to improve readability", not "always". It's not necessary in "isnan". Elsewhere the PEP talks about consistency with related code. If "isnan" is documented to do effectively the same as the C function of the same name it makes sense to use the same name. That's presumably also why "inspect.isgeneratorfunction" doesn't use underscores--they're arguably necessary, but consistency with "isfunction" trumps that. Of course it's a judgment call in borderline cases, but that's true for most of PEP 8, and it's not a problem. Also, are you sure it's really "predicate" that's the relevant difference, as opposed to, say, "short word and really short word" (which is really just a special case of "not necessary for readability"). You use "dont_write_bytecode" as an example of something that obviously needs the underscores. I think the parallel predicate looks better as "doesnt_write_bytecode" than "doesntwritebytecode" (although actually, I'd try to avoid both "don't" and "doesn't" because of the apostrophes...). And beyond your own example, "is_greater_than_one" or "can_fit_on_filesystem" seem like they need underscores, while "dotwice" seems fine without.
On 06/02/2015 07:45, Andrew Barnert wrote:
Elsewhere the PEP talks about consistency with related code. If "isnan" is documented to do effectively the same as the C function of the same name it makes sense to use the same name. That's presumably also why "inspect.isgeneratorfunction" doesn't use underscores--they're arguably necessary, but consistency with "isfunction" trumps that.
Your are right we have to keep consistency with other code, but I think we should prefer *horizontal consistency* (I mean with our codebase API) over a *vertical* one.
Also, are you sure it's really "predicate" that's the relevant difference, as opposed to, say, "short word and really short word" (which is really just a special case of "not necessary for readability").
Looking at the core and the standard library, I see we basically do not use underscore in get/set and predicates. This may be a clear general rule, and not "short word" that is not clear at all. How can you explain the following? sys.getswitchinterval() sys.setswitchinterval() asyncio.iscoroutinefunction() and: sys.exc_info() asyncio.wait_for() In these cases you can see we do not use the rule "short words", but almost always the rule: "get/set and predicates should not have underscores". I wrote almost always because sometimes we break that rule: asyncio.get_event_loop() float.is_integer() And my point is that we break it because of a lack in the PEP8. But perphaps I am alone thinking that is ugly to have this kind of inconsistency in predicates and get/set function/method names
You use "dont_write_bytecode" as an example of something that obviously needs the underscores.
I think it is not obvious at all. It is obvious just in the case we have a rule about predicates and get/set, othewise I do not understand how come it is possible that sys.dont_write_bytecode() should obviously have underscores but sys.setswitchinterval() should not.
And beyond your own example, "is_greater_than_one" or "can_fit_on_filesystem" seem like they need underscores, while "dotwice" seems fine without.
I said the opposite: is_greather_then_one() should have unserscores, and as the PEP8 says, the naming rule is the same for functions and methods. In the standard library we do not have any can_* function or method, but if in the future we will have one, then yes, I propose it should be consistent with the "predicate rule" (no underscores). -- Marco Buttu INAF-Osservatorio Astronomico di Cagliari Via della Scienza n. 5, 09047 Selargius (CA) Phone: 070 711 80 217 Email: mbuttu@oa-cagliari.inaf.it
On 06/02/2015 09:06, Marco Buttu wrote:
And beyond your own example, "is_greater_than_one" or "can_fit_on_filesystem" seem like they need underscores, while "dotwice" seems fine without.
I said the opposite: is_greather_then_one() should have unserscores, and as the PEP8 says, the naming rule is the same for functions and methods. In the standard library we do not have any can_* function or method, but if in the future we will have one, then yes, I propose it should be consistent with the "predicate rule" (no underscores).
Sorry, I mean: is_greather_then_one() should *not* have unserscores -- Marco Buttu INAF-Osservatorio Astronomico di Cagliari Via della Scienza n. 5, 09047 Selargius (CA) Phone: 070 711 80 217 Email: mbuttu@oa-cagliari.inaf.it
On Feb 6, 2015, at 0:06, Marco Buttu
On 06/02/2015 07:45, Andrew Barnert wrote
You've skipped over the most important point, the fact that the guideline explicitly says to separate words with underscores "as necessary to improve readability", not "always". Given that the entire PEP is a set of sometimes contradictory rules of thumb, very few parts of it explicitly call out the fact that they're not universal, hard and fast rules, so it's presumably important that this one actually does so. And yet you're insisting that we need extra special-case rules to give people permission to violate this rule?
Elsewhere the PEP talks about consistency with related code. If "isnan" is documented to do effectively the same as the C function of the same name it makes sense to use the same name. That's presumably also why "inspect.isgeneratorfunction" doesn't use underscores--they're arguably necessary, but consistency with "isfunction" trumps that.
Your are right we have to keep consistency with other code, but I think we should prefer *horizontal consistency* (I mean with our codebase API) over a *vertical* one.
Do you have some examples where they give different answers? Also, note that functions like math.isnan and os.getpid predate PEP 8, and aren't likely to be changed for backward compat reasons, which means any new function that's a thin wrapper around a C/POSIX stdlib function likely has as much of a horizontal consistency reason as a vertical one--e.g., if you were to add math.isnormal as a wrapper around C isnormal, you'd probably want it to be consistent with math.isnan and friends just as much as with C isnormal, right? In fact, if you look at newer functions that aren't very close parallels to existing functions in the same module or very thin wrappers around C functions, your rule doesn't seem to work. For example, in os again, getresguid matches the BSD C function and matches existing os.getguid, while get_exec_path and get_terminal_size don't have such major consistency constraints and they have underscores. Note that your new rule would leave us in the same position--we'd have some original-PEP-8-named legacy functions that we'd sometimes have to stay consistent with. Also note that this seems to work the same way for global variables/constants as for functions, as you'd expect. sys.maxunicode has a strong parallel with legacy sys.maxsize, while other attributes added around the same time mostly have underscores.
Also, are you sure it's really "predicate" that's the relevant difference, as opposed to, say, "short word and really short word" (which is really just a special case of "not necessary for readability").
Looking at the core and the standard library, I see we basically do not use underscore in get/set and predicates.
Except when we do. As in the os examples above, or all the predicate methods in pathlib.Path, or many other places where there are no relevant consistency issues.
This may be a clear general rule, and not "short word" that is not clear at all. How can you explain the following?
sys.getswitchinterval() sys.setswitchinterval() asyncio.iscoroutinefunction()
The first two are consistent with the legacy (pre-PEP8) get/setcheckinterval function, and the last is consistent with isgeneratorfunction, itself consistent with isfunction as you (I think) accepted above.
And my point is that we break it because of a lack in the PEP8.
Or we break it because sometimes consistency beats readability, and maybe occasionally some other guideline, and in rare cases because the "necessary for readability" clause is a tough judgment call.
But perphaps I am alone thinking that is ugly to have this kind of inconsistency in predicates and get/set function/method names
Given that both Python 2.1 and 3.0 decided it wasn't worth changing all the legacy names for backward-compat reasons, and you're not suggesting changing them today, I don't think there's any way to avoid having that inconsistency. But following the existing PEP 8 guidelines--adding underscores when necessary for readability except when another guideline like consistency trumps it--hasn't been a problem for the last 13 years, so I don't see it making things worse over the next 13.
You use "dont_write_bytecode" as an example of something that obviously needs the underscores.
I think it is not obvious at all. It is obvious just in the case we have a rule about predicates and get/set, othewise I do not understand how come it is possible that sys.dont_write_bytecode() should obviously have underscores but sys.setswitchinterval() should not.
Once again you've skipped over the most important point. Are you seriously suggesting that if we have a pair of related functions, they should be named "dont_write_bytecode" and "doesntwritebytecode" because the latter is a predicate?
And beyond your own example, "is_greater_than_one" or "can_fit_on_filesystem" seem like they need underscores, while "dotwice" seems fine without.
I said the opposite: is_greather_then_one() should have unserscores
No you didn't. You said predicates should _not_ have underscores. But under current PEP 8, this one probably should, and I think that's better. (If you don't agree with that one, consider a name with vowels at the word edges, like "is_any_one_among" and imagine that without the underscores.)
, and as the PEP8 says, the naming rule is the same for functions and methods. In the standard library we do not have any can_* function or method,
From a quick ack I see have can_write and friends in asyncio, can_fs_encode in distutils, cannot_convert in lib2to3, can_fetch in urllib/robotparser, a variety of can_ functions in the test suite... and not a single can\w except for cancel, canvas, and canonical.
but if in the future we will have one, then yes, I propose it should be consistent with the "predicate rule" (no underscores).
So you'd make every current can* function in the stdlib a legacy function that doesn't follow the current rules? I think you're going too far trying to make the rules complete, unambiguous, and inviolable when keeping them simple and letting humans use their judgment on the edge cases makes a lot more sense. Adding a sweeping exception to the rule that itself needs exceptions that will ultimately have a less compelling legacy justification doesn't seem like a step forward. M
On Feb 06, 2015, at 07:21 AM, Marco Buttu wrote:
I am not so crazy ;) I am just proposing a clear rule for predicates in order to avoid, _in the future_, inconsistency with the current general rule.
IMHO, there's nothing special about predicates. All else being equal, new APIs would benefit from using underscores between words for all multi-word methods. But sure, there are lots of reasons why some of our APIs don't follow that guideline. Some of those reasons are good, some are not so good <wink>. I still think it's the right guideline to promote. Cheers, -Barry
On 7 February 2015 at 03:20, Barry Warsaw
On Feb 06, 2015, at 07:21 AM, Marco Buttu wrote:
I am not so crazy ;) I am just proposing a clear rule for predicates in order to avoid, _in the future_, inconsistency with the current general rule.
IMHO, there's nothing special about predicates. All else being equal, new APIs would benefit from using underscores between words for all multi-word methods. But sure, there are lots of reasons why some of our APIs don't follow that guideline. Some of those reasons are good, some are not so good <wink>.
As one of my co-workers puts it: "sometimes things are the way they are purely for hysterical raisins"* :) Cheers, Nick. *I'm not sure how well the pun will translate for non-native English speakers, so I'll be explicit that it sounds a lot like "historical reasons" when said aloud :) -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
participants (4)
-
Andrew Barnert
-
Barry Warsaw
-
Marco Buttu
-
Nick Coghlan