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@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@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/