• [实验楼]python11期--NO.1(未完成)


    tuple 是 Python 的一种不可变数据类型,
    用于列表数据一旦初始化就不会再修改的场景。
    tuple 只能通过位置索引去访问里面的元素,
    但有时候我们需要给每个元素取个别名,
    以便通过别名去获取对应的元素。本次挑战就是需要大家自己来实现一个简单的命名 Tuple。

    功能点
    模块文件保存路径为 /home/shiyanlou/namedtuple.py
    模块内实现一个 NamedTuple 类,其构造函数接受 iterable 和 fields 两个参数,分别用于传递数据及其对应的别名
    NamedTuple 需要支持通过位置索引和别名属性两种方式去获取数据
    NamedTuple repr 输出格式类似于”NamedTuple(x=1, y=2)“,其中 x、y 是别名,1、2 是数据。
    不能使用 Python 标准库里的实现,代码里不能出现 namedtuple 相关字样

    NamedTuple 类可以继承于 tuple,但需要注意 tuple 为不可变数据类型,需要覆盖其 __new__ 方法
    为了得到想要的 repr 输出,需要实现 __repr__ 方法

    import unittest

    from namedtuple import NamedTuple


    class TestNamedTuple(unittest.TestCase):
    def test_features(self):
    fields = ['x', 'y']
    values = [1, 2]
    nt = NamedTuple(values, fields)

    self.assertEqual(nt[0], 1)
    self.assertEqual(nt[1], 2)

    self.assertEqual(nt.x, 1)
    self.assertEqual(nt.y, 2)

    self.assertEqual(repr(nt), 'NamedTuple(x=1, y=2)')
    _nt_itemgetters = {}
    
    def namedtuple(typename, field_names, *, rename=False, defaults=None, module=None):
        """Returns a new subclass of tuple with named fields.
    
        >>> Point = namedtuple('Point', ['x', 'y'])
        >>> Point.__doc__                   # docstring for the new class
        'Point(x, y)'
        >>> p = Point(11, y=22)             # instantiate with positional args or keywords
        >>> p[0] + p[1]                     # indexable like a plain tuple
        33
        >>> x, y = p                        # unpack like a regular tuple
        >>> x, y
        (11, 22)
        >>> p.x + p.y                       # fields also accessible by name
        33
        >>> d = p._asdict()                 # convert to a dictionary
        >>> d['x']
        11
        >>> Point(**d)                      # convert from a dictionary
        Point(x=11, y=22)
        >>> p._replace(x=100)               # _replace() is like str.replace() but targets named fields
        Point(x=100, y=22)
    
        """
    
        # Validate the field names.  At the user's option, either generate an error
        # message or automatically replace the field name with a valid name.
        if isinstance(field_names, str):
            field_names = field_names.replace(',', ' ').split()
        field_names = list(map(str, field_names))
        typename = _sys.intern(str(typename))
    
        if rename:
            seen = set()
            for index, name in enumerate(field_names):
                if (not name.isidentifier()
                    or _iskeyword(name)
                    or name.startswith('_')
                    or name in seen):
                    field_names[index] = f'_{index}'
                seen.add(name)
    
        for name in [typename] + field_names:
            if type(name) is not str:
                raise TypeError('Type names and field names must be strings')
            if not name.isidentifier():
                raise ValueError('Type names and field names must be valid '
                                 f'identifiers: {name!r}')
            if _iskeyword(name):
                raise ValueError('Type names and field names cannot be a '
                                 f'keyword: {name!r}')
    
        seen = set()
        for name in field_names:
            if name.startswith('_') and not rename:
                raise ValueError('Field names cannot start with an underscore: '
                                 f'{name!r}')
            if name in seen:
                raise ValueError(f'Encountered duplicate field name: {name!r}')
            seen.add(name)
    
        field_defaults = {}
        if defaults is not None:
            defaults = tuple(defaults)
            if len(defaults) > len(field_names):
                raise TypeError('Got more default values than field names')
            field_defaults = dict(reversed(list(zip(reversed(field_names),
                                                    reversed(defaults)))))
    
        # Variables used in the methods and docstrings
        field_names = tuple(map(_sys.intern, field_names))
        num_fields = len(field_names)
        arg_list = repr(field_names).replace("'", "")[1:-1]
        repr_fmt = '(' + ', '.join(f'{name}=%r' for name in field_names) + ')'
        tuple_new = tuple.__new__
        _len = len
    
        # Create all the named tuple methods to be added to the class namespace
    
        s = f'def __new__(_cls, {arg_list}): return _tuple_new(_cls, ({arg_list}))'
        namespace = {'_tuple_new': tuple_new, '__name__': f'namedtuple_{typename}'}
        # Note: exec() has the side-effect of interning the field names
        exec(s, namespace)
        __new__ = namespace['__new__']
        __new__.__doc__ = f'Create new instance of {typename}({arg_list})'
        if defaults is not None:
            __new__.__defaults__ = defaults
    
        @classmethod
        def _make(cls, iterable):
            result = tuple_new(cls, iterable)
            if _len(result) != num_fields:
                raise TypeError(f'Expected {num_fields} arguments, got {len(result)}')
            return result
    
        _make.__func__.__doc__ = (f'Make a new {typename} object from a sequence '
                                  'or iterable')
    
        def _replace(_self, **kwds):
            result = _self._make(map(kwds.pop, field_names, _self))
            if kwds:
                raise ValueError(f'Got unexpected field names: {list(kwds)!r}')
            return result
    
        _replace.__doc__ = (f'Return a new {typename} object replacing specified '
                            'fields with new values')
    
        def __repr__(self):
            'Return a nicely formatted representation string'
            return self.__class__.__name__ + repr_fmt % self
    
        def _asdict(self):
            'Return a new OrderedDict which maps field names to their values.'
            return OrderedDict(zip(self._fields, self))
    
        def __getnewargs__(self):
            'Return self as a plain tuple.  Used by copy and pickle.'
            return tuple(self)
    
        # Modify function metadata to help with introspection and debugging
    
        for method in (__new__, _make.__func__, _replace,
                       __repr__, _asdict, __getnewargs__):
            method.__qualname__ = f'{typename}.{method.__name__}'
    
        # Build-up the class namespace dictionary
        # and use type() to build the result class
        class_namespace = {
            '__doc__': f'{typename}({arg_list})',
            '__slots__': (),
            '_fields': field_names,
            '_fields_defaults': field_defaults,
            '__new__': __new__,
            '_make': _make,
            '_replace': _replace,
            '__repr__': __repr__,
            '_asdict': _asdict,
            '__getnewargs__': __getnewargs__,
        }
        cache = _nt_itemgetters
        for index, name in enumerate(field_names):
            try:
                itemgetter_object, doc = cache[index]
            except KeyError:
                itemgetter_object = _itemgetter(index)
                doc = f'Alias for field number {index}'
                cache[index] = itemgetter_object, doc
            class_namespace[name] = property(itemgetter_object, doc=doc)
    
        result = type(typename, (tuple,), class_namespace)
    
        # For pickling to work, the __module__ variable needs to be set to the frame
        # where the named tuple is created.  Bypass this step in environments where
        # sys._getframe is not defined (Jython for example) or sys._getframe is not
        # defined for arguments greater than 0 (IronPython), or where the user has
        # specified a particular module.
        if module is None:
            try:
                module = _sys._getframe(1).f_globals.get('__name__', '__main__')
            except (AttributeError, ValueError):
                pass
        if module is not None:
            result.__module__ = module
    
        return result
    nametuple源码[参考]
    Win a contest, win a challenge
  • 相关阅读:
    防止网站被镜像,被iframe
    PHP实现图片批量压缩
    常规正则表达式
    git安装项目步骤
    Laravel创建自定义 Artisan 控制台命令实例教程
    git常规命令
    JS验证身份证号
    Lucene-索引库的维护
    Lucene-分词器
    Lucene-全文检索
  • 原文地址:https://www.cnblogs.com/pandaboy1123/p/8945534.html
Copyright © 2020-2023  润新知