Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fef8546

Browse files
committed
Factor-out named tuple class definition template strings.
1 parent e84c4df commit fef8546

1 file changed

Lines changed: 60 additions & 51 deletions

File tree

Lib/collections/__init__.py

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,58 @@ def __eq__(self, other):
233233
### namedtuple
234234
################################################################################
235235

236+
_class_template = '''\
237+
class {typename}(tuple):
238+
'{typename}({arg_list})'
239+
240+
__slots__ = ()
241+
242+
_fields = {field_names!r}
243+
244+
def __new__(_cls, {arg_list}):
245+
'Create new instance of {typename}({arg_list})'
246+
return _tuple.__new__(_cls, ({arg_list}))
247+
248+
@classmethod
249+
def _make(cls, iterable, new=tuple.__new__, len=len):
250+
'Make a new {typename} object from a sequence or iterable'
251+
result = new(cls, iterable)
252+
if len(result) != {num_fields:d}:
253+
raise TypeError('Expected {num_fields:d} arguments, got %d' % len(result))
254+
return result
255+
256+
def __repr__(self):
257+
'Return a nicely formatted representation string'
258+
return self.__class__.__name__ + '({repr_fmt})' % self
259+
260+
def _asdict(self):
261+
'Return a new OrderedDict which maps field names to their values'
262+
return OrderedDict(zip(self._fields, self))
263+
264+
def _replace(_self, **kwds):
265+
'Return a new {typename} object replacing specified fields with new values'
266+
result = _self._make(map(kwds.pop, {field_names!r}, _self))
267+
if kwds:
268+
raise ValueError('Got unexpected field names: %r' % kwds.keys())
269+
return result
270+
271+
def __getnewargs__(self):
272+
'Return self as a plain tuple. Used by copy and pickle.'
273+
return tuple(self)
274+
275+
{field_defs}
276+
'''
277+
278+
_repr_template = '{name}=%r'
279+
280+
_field_template = '''\
281+
{name} = _property(_itemgetter({index:d}), doc='Alias for field number {index:d}')
282+
'''
283+
236284
def namedtuple(typename, field_names, verbose=False, rename=False):
237285
"""Returns a new subclass of tuple with named fields.
238286
239-
>>> Point = namedtuple('Point', 'x y')
287+
>>> Point = namedtuple('Point', ['x', 'y'])
240288
>>> Point.__doc__ # docstring for the new class
241289
'Point(x, y)'
242290
>>> p = Point(11, y=22) # instantiate with positional args or keywords
@@ -287,66 +335,27 @@ def namedtuple(typename, field_names, verbose=False, rename=False):
287335
raise ValueError('Encountered duplicate field name: %r' % name)
288336
seen_names.add(name)
289337

290-
# Create and fill-in the class template
291-
template = '''class {typename}(tuple):
292-
'{typename}({argtxt})'
293-
294-
__slots__ = ()
295-
296-
_fields = {field_names!r}
297-
298-
def __new__(_cls, {argtxt}):
299-
'Create new instance of {typename}({argtxt})'
300-
return _tuple.__new__(_cls, ({argtxt}))
301-
302-
@classmethod
303-
def _make(cls, iterable, new=tuple.__new__, len=len):
304-
'Make a new {typename} object from a sequence or iterable'
305-
result = new(cls, iterable)
306-
if len(result) != {numfields:d}:
307-
raise TypeError('Expected {numfields:d} arguments, got %d' % len(result))
308-
return result
309-
310-
def __repr__(self):
311-
'Return a nicely formatted representation string'
312-
return self.__class__.__name__ + '({reprtxt})' % self
313-
314-
def _asdict(self):
315-
'Return a new OrderedDict which maps field names to their values'
316-
return OrderedDict(zip(self._fields, self))
317-
318-
def _replace(_self, **kwds):
319-
'Return a new {typename} object replacing specified fields with new values'
320-
result = _self._make(map(kwds.pop, {field_names!r}, _self))
321-
if kwds:
322-
raise ValueError('Got unexpected field names: %r' % kwds.keys())
323-
return result
324-
325-
def __getnewargs__(self):
326-
'Return self as a plain tuple. Used by copy and pickle.'
327-
return tuple(self)
328-
329-
'''
330-
template = template.format(
338+
# Fill-in the class template
339+
class_definition = _class_template.format(
331340
typename = typename,
332341
field_names = field_names,
333-
argtxt = repr(field_names).replace("'", "")[1:-1],
334-
numfields = len(field_names),
335-
reprtxt = ', '.join('{}=%r'.format(name) for name in field_names),
342+
num_fields = len(field_names),
343+
arg_list = repr(field_names).replace("'", "")[1:-1],
344+
repr_fmt = ', '.join(_repr_template.format(name=name) for name in field_names),
345+
field_defs = '\n'.join(_field_template.format(index=index, name=name)
346+
for index, name in enumerate(field_names))
336347
)
337-
for i, name in enumerate(field_names):
338-
template += " %s = _property(_itemgetter(%d), doc='Alias for field number %d')\n" % (name, i, i)
339348
if verbose:
340-
print(template)
349+
print(class_definition)
341350

342-
# Execute the template string in a temporary namespace and
351+
# Execute the class definition string in a temporary namespace and
343352
# support tracing utilities by setting a value for frame.f_globals['__name__']
344353
namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
345354
OrderedDict=OrderedDict, _property=property, _tuple=tuple)
346355
try:
347-
exec(template, namespace)
356+
exec(class_definition, namespace)
348357
except SyntaxError as e:
349-
raise SyntaxError(e.msg + ':\n\n' + template)
358+
raise SyntaxError(e.msg + ':\n\n' + class_definition)
350359
result = namespace[typename]
351360

352361
# For pickling to work, the __module__ variable needs to be set to the frame

0 commit comments

Comments
 (0)