zoukankan      html  css  js  c++  java
  • collections额外数据类型

    collections --- 容器数据类型


    这个模块实现了特定目标的容器,以提供Python标准内建容器 dict , list , set , 和 tuple的替代选择。

    namedtuple()

    创建命名元组子类的工厂函数

    deque

    类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)

    ChainMap

    类似字典(dict)的容器类,将多个映射集合到一个视图里面

    Counter

    字典的子类,提供了可哈希对象的计数功能

    OrderedDict

    字典的子类,保存了他们被添加的顺序

    defaultdict

    字典的子类,提供了一个工厂函数,为字典查询提供一个默认值

    UserDict

    封装了字典对象,简化了字典子类化

    UserList

    封装了列表对象,简化了列表子类化

    UserString

    封装了列表对象,简化了字符串子类化

    namedtuple() 命名元组的工厂函数

    命名元组赋予每个位置一个含义,提供可读性和自文档性。它们可以用于任何普通元组,并添加了通过名字获取值的能力,通过索引值也是可以的。

    collections.namedtuple(typenamefield_names*rename=Falsedefaults=Nonemodule=None)

    返回一个新的元组子类,名为 typename 。这个新的子类用于创建类元组的对象,可以通过域名来获取属性值,同样也可以通过索引和迭代获取值。子类实例同样有文档字符串(类名和域名)另外一个有用的 __repr__() 方法,以 name=value 格式列明了元组内容。

    field_names 是一个像 [‘x’, ‘y’] 一样的字符串序列。另外 field_names 可以是一个纯字符串,用空白或逗号分隔开元素名,比如 'x y' 或者 'x, y' 。

    任何有效的Python 标识符都可以作为域名,除了下划线开头的那些。有效标识符由字母,数字,下划线组成,但首字母不能是数字或下划线,另外不能是关键词 keyword 比如 classforreturnglobalpass, 或 raise 。

    如果 rename 为真, 无效域名会自动转换成位置名。比如 ['abc', 'def', 'ghi','abc'] 转换成 ['abc', '_1', 'ghi', '_3'] , 消除关键词 def 和重复域名 abc 。

    defaults 可以为 None 或者是一个默认值的 iterable 。如果一个默认值域必须跟其他没有默认值的域在一起出现,defaults 就应用到最右边的参数。比如如果域名 ['x', 'y','z'] 和默认值 (1, 2) ,那么 x 就必须指定一个参数值 ,y 默认值 1 , z 默认值 2 。

    如果 module 值有定义,命名元组的 __module__ 属性值就被设置。

    命名元组实例没有字典,所以它们要更轻量,并且占用更小内存。

    在 3.1 版更改: 添加了对 rename 的支持。

    在 3.6 版更改: verbose 和 rename 参数成为 仅限关键字参数.

    在 3.6 版更改: 添加了 module 参数。

    在 3.7 版更改: 移去了 verbose 参数和属性 _source 。

    在 3.7 版更改: 添加了 defaults 参数和 _field_defaults 属性。

    >>> # Basic example
    >>> Point = namedtuple('Point', ['x', 'y'])
    >>> p = Point(11, y=22)     # instantiate with positional or keyword arguments
    >>> p[0] + p[1]             # indexable like the plain tuple (11, 22)
    33
    >>> x, y = p                # unpack like a regular tuple
    >>> x, y
    (11, 22)
    >>> p.x + p.y               # fields also accessible by name
    33
    >>> p                       # readable __repr__ with a name=value style
    Point(x=11, y=22)
    

    命名元组尤其有用于赋值 csv sqlite3 模块返回的元组

    EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
    
    import csv
    for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
        print(emp.name, emp.title)
    
    import sqlite3
    conn = sqlite3.connect('/companydata')
    cursor = conn.cursor()
    cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
    for emp in map(EmployeeRecord._make, cursor.fetchall()):
        print(emp.name, emp.title)
    

    除了继承元组的方法,命名元组还支持三个额外的方法和两个属性。为了防止域名冲突,方法和属性以下划线开始。

    classmethod somenamedtuple._make(iterable)

    类方法从存在的序列或迭代实例创建一个新实例。

    >>> t = [11, 22]
    >>> Point._make(t)
    Point(x=11, y=22)
    
    somenamedtuple._asdict()

    返回一个新的 dict ,它将字段名称映射到它们对应的值:

    >>> p = Point(x=11, y=22)
    >>> p._asdict()
    OrderedDict([('x', 11), ('y', 22)])
    

    在 3.1 版更改: 返回一个 OrderedDict 而不是 dict 。

    somenamedtuple._replace(**kwargs)

    返回一个新的命名元组实例,并将指定域替换为新的值

    >>>
    >>> p = Point(x=11, y=22)
    >>> p._replace(x=33)
    Point(x=33, y=22)
    
    >>> for partnum, record in inventory.items():
    ...     inventory[partnum] = record._replace(price=newprices[partnum], timestamp=time.now())
    
    somenamedtuple._fields

    字符串元组列出了域名。用于提醒和从现有元组创建一个新的命名元组类型。

    >>> p._fields            # view the field names
    ('x', 'y')
    
    >>> Color = namedtuple('Color', 'red green blue')
    >>> Pixel = namedtuple('Pixel', Point._fields + Color._fields)
    >>> Pixel(11, 22, 128, 255, 0)
    Pixel(x=11, y=22, red=128, green=255, blue=0)
    
    somenamedtuple._field_defaults

    默认值的字典。

    >>> Account = namedtuple('Account', ['type', 'balance'], defaults=[0])
    >>> Account._field_defaults
    {'balance': 0}
    >>> Account('premium')
    Account(type='premium', balance=0)
    

    要获取这个名字域的值,使用 getattr() 函数 :

    >>> getattr(p, 'x')
    11
    

    要将字典转换为命名元组,请使用 ** 运算符(如 解包参数列表 中所述):

    >>> d = {'x': 11, 'y': 22}
    >>> Point(**d)
    Point(x=11, y=22)
    

    因为一个命名元组是一个正常的Python类,它可以很容易的通过子类更改功能。这里是如何添加一个计算域和定宽输出打印格式:

    >>> class Point(namedtuple('Point', ['x', 'y'])):
    ...     __slots__ = ()
    ...     @property
    ...     def hypot(self):
    ...         return (self.x ** 2 + self.y ** 2) ** 0.5
    ...     def __str__(self):
    ...         return 'Point: x=%6.3f  y=%6.3f  hypot=%6.3f' % (self.x, self.y, self.hypot)
    
    >>> for p in Point(3, 4), Point(14, 5/7):
    ...     print(p)
    Point: x= 3.000  y= 4.000  hypot= 5.000
    Point: x=14.000  y= 0.714  hypot=14.018
    

    上面的子类设置 __slots__ 为一个空元组。通过阻止创建实例字典保持了较低的内存开销。

    子类化对于添加和存储新的名字域是无效的。应当通过 _fields 创建一个新的命名元组来实现它:

    >>> Point3D = namedtuple('Point3D', Point._fields + ('z',))
    

    文档字符串可以自定义,通过直接赋值给 __doc__ 属性:

    >>> Book = namedtuple('Book', ['id', 'title', 'authors'])
    >>> Book.__doc__ += ': Hardcover book in active collection'
    >>> Book.id.__doc__ = '13-digit ISBN'
    >>> Book.title.__doc__ = 'Title of first printing'
    >>> Book.authors.__doc__ = 'List of authors sorted by last name'
    

    在 3.5 版更改: 文档字符串属性变成可写。

    默认值可以用 _replace() 来实现, 通过自定义一个原型实例:

    >>> Account = namedtuple('Account', 'owner balance transaction_count')
    >>> default_account = Account('<owner name>', 0.0, 0)
    >>> johns_account = default_account._replace(owner='John')
    >>> janes_account = default_account._replace(owner='Jane')
    

    参见

    • 请参阅 typing.NamedTuple ,以获取为命名元组添加类型提示的方法。 它还使用 class 关键字提供了一种优雅的符号:

      class Component(NamedTuple):
          part_number: int
          weight: float
          description: Optional[str] = None
      
    • 对于以字典为底层的可变域名, 参考 types.SimpleNamespace() 。

    • dataclasses 模块提供了一个装饰器和一些函数,用于自动将生成的特殊方法添加到用户定义的类中。

    • OrderedDict 对象

      有序词典就像常规词典一样,但有一些与排序操作相关的额外功能。由于内置的 dict 类获得了记住插入顺序的能力(在 Python 3.7 中保证了这种新行为),它们变得不那么重要了。

      一些与 dict 的不同仍然存在:

      • 常规的 dict 被设计为非常擅长映射操作。 跟踪插入顺序是次要的。

      • OrderedDict 旨在擅长重新排序操作。 空间效率、迭代速度和更新操作的性能是次要的。

      • 算法上, OrderedDict 可以比 dict 更好地处理频繁的重新排序操作。 这使其适用于跟踪最近的访问(例如在 LRU cache 中)。

      • 对于 OrderedDict ,相等操作检查匹配顺序。

      • OrderedDict 类的 popitem() 方法有不同的签名。它接受一个可选参数来指定弹出哪个元素。

      • OrderedDict 类有一个 move_to_end() 方法,可以有效地将元素移动到任一端。

      • Python 3.8之前, dict 缺少 __reversed__() 方法。

      class collections.OrderedDict([items])

      返回一个 dict 子类的实例,它具有专门用于重新排列字典顺序的方法。

      3.1 新版功能.

      popitem(last=True)

      有序字典的 popitem() 方法移除并返回一个 (key, value) 键值对。 如果 last 值为真,则按 LIFO 后进先出的顺序返回键值对,否则就按 FIFO 先进先出的顺序返回键值对。

      move_to_end(keylast=True)

      将现有 key 移动到有序字典的任一端。 如果 last 为真值(默认)则将元素移至末尾;如果 last 为假值则将元素移至开头。如果 key 不存在则会触发 KeyError:

      >>>
      >>> d = OrderedDict.fromkeys('abcde')
      >>> d.move_to_end('b')
      >>> ''.join(d.keys())
      'acdeb'
      >>> d.move_to_end('b', last=False)
      >>> ''.join(d.keys())
      'bacde'
      

      3.2 新版功能.

      相对于通常的映射方法,有序字典还另外提供了逆序迭代的支持,通过 reversed() 。

      OrderedDict 之间的相等测试是顺序敏感的,实现为 list(od1.items())==list(od2.items()) 。 OrderedDict 对象和其他的 Mapping 的相等测试,是顺序敏感的字典测试。这允许 OrderedDict 替换为任何字典可以使用的场所。

      在 3.5 版更改: OrderedDict 的项(item),键(key)和值(value) 视图 现在支持逆序迭代,通过 reversed() 。

      在 3.6 版更改: PEP 468 赞成将关键词参数的顺序保留, 通过传递给 OrderedDict 构造器和它的 update() 方法。

      OrderedDict 例子和用法

      创建记住键值 最后 插入顺序的有序字典变体很简单。 如果新条目覆盖现有条目,则原始插入位置将更改并移至末尾:

      class LastUpdatedOrderedDict(OrderedDict):
          'Store items in the order the keys were last added'
      
          def __setitem__(self, key, value):
              super().__setitem__(key, value)
              super().move_to_end(key)
      

      一个 OrderedDict 对于实现 functools.lru_cache() 的变体也很有用:

      class LRU(OrderedDict):
          'Limit size, evicting the least recently looked-up key when full'
      
          def __init__(self, maxsize=128, *args, **kwds):
              self.maxsize = maxsize
              super().__init__(*args, **kwds)
      
          def __getitem__(self, key):
              value = super().__getitem__(key)
              self.move_to_end(key)
              return value
      
          def __setitem__(self, key, value):
              super().__setitem__(key, value)
              if len(self) > self.maxsize:
                  oldest = next(iter(self))
                  del self[oldest
  • 相关阅读:
    C#设置窗体最大化且不遮挡任务栏的方法
    C# Base64解码 二进制输出
    导出Excel并下载,但无法定制样式的方法!
    C# List 转Datatable
    查询sql语句耗时的方法!
    301跳转
    文章关键字加链接
    文本框样式默认文本
    JForum二次开发(一)
    MongoDB 学习笔记(三)—— 修改器的使用
  • 原文地址:https://www.cnblogs.com/huahongzhenghexiu/p/11900245.html
Copyright © 2011-2022 走看看