I realised I’m making some assumptions around the “split constructor signature” idea that neither I nor @zuo have explicitly stated (and my assumptions may not be the same as @zuo’s), so writing those down:
- I’m assuming the basic type creation signature would be a simplified formatting syntax that only supports auto-numbered style format strings (no field expressions), and accepts an iterable of values. The
expr
field on the interpolations would be populated with the empty string to indicate the lack of an explicit expression in the template definition. - If private
re
-style caching of the dynamic templates is included, it would just use a regularTemplate
instance with the fieldvalue
attributes set to eitherEllipsis
orNone
(I don’t think the choice matters much, since the caching would be a private API) - Supporting full dynamic templating would be deferred to a later PEP (more on that below)
- The final line of the default constructor would be defined as
return cls.from_segments(*segments)
, so subclasses only need to overrideTemplate.from_segments
to change the way construction works (such as pre-quoting replacement field values, so naive formatting becomes safe).
The reason I’d still like to defer full dynamic template field formatting (with class methods like Template.from_format
and Template.from_format_map
) is that we don’t have a nice building block that would let us easily represent the dynamic attribute and subscript retrieval that the full dynamic string formatting syntax supports. (I’m less worried about format string interpolation, since that can be handled by “templating the template”)
Specifically things like {0.metrics.weight}
and {players[0].name}
(inspired by the examples in string — Common string operations — Python 3.13.0 documentation).
While I think these could reasonably be represented as a lookup_chain
list consisting of itemgetter()
and attrgetter()
instances, there are enough additional questions raised that it seems worth postponing these topics to a PEP that can fully focus on them, separately from the underlying foundation of the template string syntax definition and implementation.
Since I now also think we’d want to keep UnboundField
and UnboundTemplate
as their own types (separate from the bound versions, since we can’t actually make them behave identically due to the missing field value information in the unbound variants), accepting PEP 750 without these features wouldn’t be locking us out of anything. Even if PEP 750 doesn’t split the construction signature, we’re not locked out of anything - it just means anyone wanting to do dynamic templating in the meantime would need to build their own on top of string.Formatter
instead of Template
providing a native way to do it.
Once UnboundTemplate
and UnboundField
were defined, then the dynamic template caching could be defined in terms of those, and hence provide a foundation for offering Template.from_format
and Template.from_format_map
.