[Tutor] CONSTANTS -- Is it appropriate to use uppercase names within a function or method?

Mats Wichmann mats at wichmann.us
Tue Nov 12 14:07:48 EST 2019


On 11/12/19 10:43 AM, boB Stepp wrote:
> As I begin to play around with my newly installed editor tools, pylint
> does not like the following:

To just answer the question you asked first:

 > What I am asking about is the flagging of "COUNT_TODAY_TOO = 1"

 > I guess the bottom line question is:  What should I have done?

The style preference is to define such a constant (uppercased) at the 
module level - that is, at the top of the file somewhere, not inside the 
scope of a function definition. Particularly works well as you use it 
more than once.  That should quiet pylint; or you could lowercase the 
name leaving it inside the function and pylint will think it's an 
"appropriate" local variable name.  This is certainly a PEP-8 style 
thing, one I'm not personally in love with, but I'll happily go along if 
"PEP 8 conformance" is a requirement of what I'm working on. You can 
also configure pylint not to issue that particular warning - describing 
how is a bit out of scope for this message.

===

> 
>     def get_days_to_goal(goal_date_obj, start_date_obj=None):
> --    """Given a start date object and a goal date object, return the
> number of
>        days it will take to attain a goal, counting the start date as
> one of these
>        days.
> 
>        start_date_obj:  A date object giving the start date for further
>            calculations.
> 
>        goal_date_obj:  A date object giving the date by which the goal
> should be
>            attained.
> 
>        days_to_goal:  An integer giving the number of days to achieve the goal,
>            counting today as one of those days.
>        """
...
 > Please ignore the flagging of the function docstring.  I need to
 > reread the docstring PEP.  Apparently I need to make the first line of
 > the docstring a short one-line summary sentence ending in a period.

Blatantly failing to follow your instructions :)  - right, one-line 
summary of what it does, followed by a blank line followed by a more 
detailed description, if such is needed.  Since your longer description 
already says what the start and goal dates are, it seems the description 
of what it does is:

Return the number of days it will take to attain a goal

===

Your function signature has two parameters, your docstring has three, 
which hints at a mismatch. Since you're playing with tools anyway, you 
could let the tools generate the initial docstring, then you can fill it 
in.  Many editors have some way to generate a template docstring (often 
with a selector to pick the style of docstring markup you prefer), and 
for those that don't, the external Pyment tool could do that. I pasted 
just the function signature (followed by pass) into a file and it 
generated this:

# Patch generated by Pyment v0.3.3

--- a/x.py
+++ b/x.py
@@ -1,3 +1,9 @@

  def get_days_to_goal(goal_date_obj, start_date_obj=None):
+    """
+
+    :param goal_date_obj:
+    :param start_date_obj:  (Default value = None)
+
+    """
      pass


or if you prefer the more human-readable Google style:

# Patch generated by Pyment v0.3.3

--- a/x.py
+++ b/x.py
@@ -1,3 +1,12 @@

  def get_days_to_goal(goal_date_obj, start_date_obj=None):
+    """
+
+    Args:
+      goal_date_obj:
+      start_date_obj:  (Default value = None)
+
+    Returns:
+
+    """
      pass

Don't document days_to_goal in the docstring - it's just a variable (an 
obvious one at that) internal to the function, which then is immediately 
returned.

===

Since this function has a very specific expectation of the types of the 
arguments, you could add type hints to say so, and your tooling should 
warn you if there are mismatches.  e.g.,  assuming you've done

from datetime import date

so that date is a known symbol, you can rewrite your signature annotated 
like so:

def get_days_to_goal(goal_date_obj: date, start_date_obj: date = None) 
-> int:


I'm not (yet?) a "use type hints everywhere" guy, but this seems like a 
good place for it - your function would blow up if sent parameters of 
different types than a datetime.date, so it's useful to provide a way 
for at least some tooling to detect that - or else program the function 
a bit more defensively.


More information about the Tutor mailing list