[Python-ideas] Better repr() for sentinel objects

Bruce Leban bruce at leapyear.org
Sat Feb 15 20:28:42 CET 2014


A class like this is useful although I've called it NamedObject (by analogy
to NamedTuple). It's useful in contexts other than as a sentinel, for
example to represent deleted values, but the fundamental aspects are that
it's a unique object that has a name.

I've done two different things in my case:

(1) add __setattr__ so you can't set values on this object (to prevent
someone that gets the object from operating on it as if it's some other
object).

(2) printing str(descr) not repr(descr). Since the standard use case is
passing a string to the constructor, it's not valuable for it to print
quotes around it. I also use <> instead of NamedObject() but I don't care
about that distinction.

>>> a = NamedObject('DELETED'), NamedObject('DELETED')
>>> a
(<DELETED>, <DELETED>)
>>> a[0] == a[1]
False


Note the last line: this is different from how unittest.mock.sentinel
works. I find both cases useful (and particularly find the
unittest.mock.sentinel version more useful in unittests).

Writing this up I suppose UniqueObject might be a better name for this than
NamedObject.

--- Bruce
Learn how hackers think: http://j.mp/gruyere-security


On Sat, Feb 15, 2014 at 3:56 AM, Chris Angelico <rosuav at gmail.com> wrote:

> A common pattern, both in the stdlib and in user code, is the
> dedicated sentinel object to recognize an omitted argument:
>
> no_timeout = object()
> def get_data(source, timeout=no_timeout):
>     if timeout is not no_timeout:
>         source.set_alarm(timeout)
>     return source.pop()
>
> This is a bit unclear in the function signature, as seen in help():
>
> """
> Help on function get_data in module __main__:
>
> get_data(source, timeout=<object object at 0x7f579fe53070>)
> """
>
> The stdlib does this:
> """
> Help on function create_connection in module socket:
>
> create_connection(address, timeout=<object object at 0x7fe52900b080>,
> source_address=None)
> """ # chomp docstring
>
> """
> Help on function urlopen in module urllib.request:
>
> urlopen(url, data=None, timeout=<object object at 0x7fe52900b080>, *,
> cafile=None, capath=None, cadefault=False)
> """ # no docstring to chomp, actually
>
> It's not particularly useful to get the object's address. Proposal: A
> self-documenting Sentinel class which serves the exact same purpose.
>
> class Sentinel:
>     def __init__(self, desc):
>         self.desc = desc
>     def __repr__(self):
>         return "Sentinel(" + repr(self.desc) + ")"
>
> This can then be used just like object(), only it retains something
> for the benefit of its repr:
>
> no_timeout = Sentinel("No timeout")
> # Same function definition
> """
> Help on function get_data in module __main__:
>
> get_data(source, timeout=Sentinel('No timeout'))
> """
>
> I don't know how this interacts with Argument Clinic and C-written
> functions. If there's something that's being done for those that would
> make sentinels come out a particular way in their help() info, ideally
> this should be displayed the same way (or at least similarly).
>
> Thoughts?
>
> ChrisA
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20140215/53f4e703/attachment.html>


More information about the Python-ideas mailing list