On Thu, Nov 25, 2010 at 3:41 AM, Michael Foord <fuzzy...@voidspace.org.uk> wrote: > Can you explain what you see as the difference? > > I'm not particularly interested in type validation but I like the fact that > typical enum APIs allow you to group constants: the generated constant class > acts as a namespace for all the defined constants.
The problem with blessing one particular "enum API" is that people have so many different ideas as to what an enum API should look like. However, the one thing they all have in common is the ability to take a value and give it a name, then present *both* of those in debugging information. > Are you just suggesting something along the lines of: > > class NamedConstant(int): > def __new__(cls, name, val): > return int.__new__(cls, val) > > def __init__(self, name, val): > self._name = name > > def __repr__(self): > return '<NamedConstant %s>' % self._name > > FOO = NamedConstant('FOO', 3) > > In general the less features the better, but I'd like a few more features > than that. :-) Not quite. I'm suggesting a factory function that works for any value, and derives the parent class from the type of the supplied value. However, what you wrote is still the essence of the idea - we would be primarily providing a building block that makes it easier for people to *create* enum APIs if they want to, but for simple use cases (where all they really wanted was the enhanced debugging information) they wouldn't need to bother. In the standard library, wherever we do "enum-like things" we would switch to using named values where it makes sense to do so. Doing so may actually make sense for more than just constants - it may make sense for significant mutable globals as well. ========================================================================== # Implementation (more than just a sketch, since it handles some interesting corner cases) import functools @functools.lru_cache() def _make_named_value_type(base_type): class _NamedValueType(base_type): def __new__(cls, name, value): return base_type.__new__(cls, value) def __init__(self, name, value): self.__name = name super().__init__(value) @property def _name(self): return self.__name def _raw(self): return base_type(self) def __repr__(self): return "{}={}".format(self._name, super().__repr__()) if base_type.__str__ is object.__str__: __str__ = base_type.__repr__ _NamedValueType.__name__ = "Named<{}>".format(base_type.__name__) return _NamedValueType def named_value(name, value): return _make_named_value_type(type(value))(name, value) def set_named_values(namespace, **kwds): for k, v in kwds.items(): namespace[k] = named_value(k, v) x = named_value("FOO", 1) y = named_value("BAR", "Hello World!") z = named_value("BAZ", dict(a=1, b=2, c=3)) print(x, y, z, sep="\n") print("\n".join(map(repr, (x, y, z)))) print("\n".join(map(str, map(type, (x, y, z))))) set_named_values(globals(), foo=x._raw(), bar=y._raw(), baz=z._raw()) print("\n".join(map(repr, (foo, bar, baz)))) print(type(x) is type(foo), type(y) is type(bar), type(z) is type(baz)) ========================================================================== # Session output for the last 6 lines >>> print(x, y, z, sep="\n") 1 Hello World! {'a': 1, 'c': 3, 'b': 2} >>> print("\n".join(map(repr, (x, y, z)))) FOO=1 BAR='Hello World!' BAZ={'a': 1, 'c': 3, 'b': 2} >>> print("\n".join(map(str, map(type, (x, y, z))))) <class '__main__.Named<int>'> <class '__main__.Named<str>'> <class '__main__.Named<dict>'> >>> set_named_values(globals(), foo=x._raw(), bar=y._raw(), baz=z._raw()) >>> print("\n".join(map(repr, (foo, bar, baz)))) foo=1 bar='Hello World!' baz={'a': 1, 'c': 3, 'b': 2} >>> print(type(x) is type(foo), type(y) is type(bar), type(z) is type(baz)) True True True For "normal" use, such objects would look like ordinary instances of their class. They would only behave differently when their representation is printed (prepending their name), or when their type is interrogated (being an instance of the named subclass rather than the ordinary type). Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com