[Python-ideas] Specifying constants for functions

Steven D'Aprano steve at pearwood.info
Tue Oct 27 19:36:50 EDT 2015


On Tue, Oct 27, 2015 at 04:30:41PM -0400, Yury Selivanov wrote:
> 
> 
> On 2015-10-27 4:22 PM, Nikolaus Rath wrote:
> >Because it leaks into the enclosing scope.
> 
> Leaks what?
> Name?  Name it _SENTINEL then.

It is still in the enclosing scope.

Bruce is right that what we really want is something like "static". 
Lacking that feature, one work-around is "make it a global variable, and 
give it a leading underscore", but that's just a work-around.

Consider:

_SENTINEL = object()

# Later:
def spam(): ...
def eggs(): ...
def cheese(): ...
def aardvark(): ...


As the module user, you can see the leading underscore in _SENTINEL 
and immediately forget all about it. But as the module maintainer, you 
cannot ignore _SENTINEL. Leading underscore or not, it is still part of 
the implementation, and maintenance is all about the implementation.

Which of the functions uses _SENTINEL? You can assume that *at least* 
one function uses it, but it may be more. Is it safe to rename it? 
Change it's value? To the maintainer, _SENTINEL is just another global 
variable, with all the disadvantages that has.

Better to put it inside the function, so the maintainer knows that it is 
local to the function:

def spam():
    SENTINEL = object()
    ...


That's not bad, but what if the value is something harder to calculate?

def spam():
    SENTINEL = next_prime_number(2**512)
    ...


At the moment, Python has an obvious way to calculate a value once only 
(make it a module-level global), and there is an obvious way to make a 
value local to a function (put it inside the function body). But there's 
no obvious way to do both together:

"Calculate this thing once only, AND make it local to this scope."

The unobvious and ugly way is to put the calculation in the function 
declaration as a default value:

def spam(SENTINEL=next_prime_number(2**512)):
    ...


which complicates the function signature and risks errors if the caller 
accidentally calls the function with too many arguments.


-- 
Steve


More information about the Python-ideas mailing list