What I want out a Symbol type in Python
Back in OptionalArgumentsIssue, I wrote that special unique sentinel values were one of the cases where it would be nice to have a real symbol type in Python (ideally including syntactic support). This raises the question of how such a type would behave and what sort of special support it needs.
Unfortunately, what I really want requires language support. Without it, the best we can do is something like this:
>>> no_arg = Symbol("no_arg") >>> print no_arg Symbol("no_arg") >>> no_arg is Symbol("no_arg") False
This gives us unique named objects and lets us us dump the symbol's name (if we gave it one) to help with debugging, but that's it. What we really want is not to have to repeat the symbol's name when we create it and for symbols to be unique in the current module; ideally there would be a less verbose syntax for creating symbols, too.
(We don't want named symbols to be globally unique, because that risks
confusing my module's
no_arg symbol with your module's
symbol; implicit global namespaces are a bad idea. At the same time
fully unique named symbols are somewhat absurd, as illustrated here.
Module unique symbols are a reasonable compromise since we can say they
correspond reasonably well to module level variables.)
I believe that in theory we can create module unique named symbols and mostly avoid repetition in pure Python code. However it would require relatively ugly hacks behind the back of CPython, hacks that would surprise people reading code that used symbols and not be fully reliable. To do this properly you really need interpreter support, and that should really come with special syntax so that people understand how special these symbols are.
(Unfortunately I'm not sure that Ruby's
:name syntax for symbols would
work given how Python syntax already uses
: in various places.)
Sidebar: a really basic Symbol class
We can construct a really basic Symbol type fairly simply:
class Symbol(object): __slots__ = ('name',) def __init__(self, name = None): self.name = name def __repr__(self): if not self.name: return super(Symbol, self).__repr__() return "<Symbol: %s>" % self.name def __str__(self): if not self.name: return super(Symbol, self).__str__() return "Symbol('%s')" % self.name
In this version, named symbols are fully unique.