[Tutor] s.insert(i, x) explanation in docs for Python 3.4 confusing to me
Cameron Simpson
cs at zip.com.au
Sun Jan 17 05:18:22 EST 2016
On 16Jan2016 22:42, Alex Kleider <akleider at sonic.net> wrote:
>On 2016-01-16 18:02, Cameron Simpson wrote:
>>much like writing a function "def f(x, y=None)"; None is a sentinel
>>value - specially recognised as nor in the normal domain for that
>>value.
>
>Can you please clarify the last bit:
>"specially recognised as nor in the normal domain for that value."
s/nor/not/
The domain of a function (or value) is the set of valid values it may take. The
range is the set of values it may produce.
A sentinel value is a special value you may encounter in a data set (or as a
value) which is _not_ part of the normal domain; often it indicates the end of
a sequence (hence the name, like a border guard). In Python the special value
None is often used as a sentinel value. Since all names have _some_ value, if
you need to indicate that this name "isn't set" or "doesn't specify a valid
value", you need a sentinal value, often "None".
So the common idiom for default values in Python function definitions:
def func(a, b, c=None):
if c is None:
c = default-value-for-c
...
indicates that the parameters "a" and "b must be supplied, and "c" is optional.
If not supplied it will have the value "None". This is a sentinel value so that
"func" can distinguish a valid value from a value not supplied.
You can also use them to indicate the end of data in some sense. If you're
looking at a text file as lines of printable characters, the newline character
at the end of the line could be considered a sentinel. Also consider a Queue:
there's no notion of "closed" in the stdlib version, so one might put a None on
the queue to indicate to the consumer that there will be no more items.
It isn't always None. Sometimes you may want to pass None as normal data, or
you have no control over what is passed around. In that case you might need to
make a unique sentinel value entirely for your object. The normal way to do
this is simply to make a new object:
sentinel = object()
This is a minimal Python object which nobody else is using. Its value is
nothing special (or even meaningful), so you merely want to check whether what
you've got is that particular object, using "is". Untested example sketch:
class SomethingLikeAQueue:
def __init__(self,......):
self.things = []
# private value to use as a sentinel, unique per instance
self._sentinel = object()
... whatever else ...
def put(self, value):
# public method to put a new value
if value is self._sentinel:
raise ValueError("you may not put the sentinel value")
self._put(value)
def _put(self, value):
# private method accepting any value including the sentinel
# we will use receipt of the sentinel to process the things and stop
# further acceptance of more things
if value is self._sentinel:
things = self.things
self.things = None # will make the .append blow up
... process things here maybe ...
else:
things.append(value)
def close(self):
# send the sentinel to indicate no more things
self._put(self._sentinel)
Cheers,
Cameron Simpson <cs at zip.com.au>
More information about the Tutor
mailing list