Python:collections.namedtuple详解

前提

由于tuple具有局限性:不能为元组内部的数据进行命名,所以往往我们并不知道元组内部每个位置的内容代表什么意思

因此在这里引入了 collections.namedtuple 这个工厂函数,来构造一个带字段名的元组。

🎶注:工厂模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。

  • 使用namedtuple会创建一个元组的子类(工厂),需用通过实例化(创建工作)才能创建具体的对象

基本概念

命名元组(namedtuple)可以赋予元组每个位置含义。它们可以用于任何普通元组,并添加了通过名字获取值的能力,通过索引值也是可以的。

参数解析

collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
  • typename:必填

    要生成的元组子的名字,例如Point

  • field_names:必填

    用于定义每个位置的含义

    • 可以是一个字符串序列,例如[x, y]

    • 可以是一个纯字符串,用空白或逗号分隔开元素名,比如 'x y' 或者 'x, y'

      Point = namedtuple('Point', ['x', 'y'])
      Point = namedtuple('Point', 'x y')
      Point = namedtuple('Point', 'x, y')
      
  • rename:选填,默认为False

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

    Point = namedtuple('Point', ['abc', 'def', 'ghi', 'abc'], rename=True)
    a = Point(1,2,3,4)
    print(a)
    # Point(abc=1, _1=2, ghi=3, _3=4)
    
  • defaults:选填,默认为None

    可以为 None 或者是一个默认值的 iterable,由于具有默认值的字段必须位于没有默认值的字段之后,因此在defaults在与field_names进行匹配的时候,会从右向左匹配。例如field_names['x', 'y', 'z']defaults(1, 2) ,那么 x 就必须指定一个参数值 ,y 默认值 1z 默认值 2

    Point = namedtuple('Point', ['x', 'y', 'z'], defaults=(1,2))
    a = Point(666)
    print(a)
    # Point(x=666, y=1, z=2)
    
  • module:选填,默认为None

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

    Point1 = namedtuple('Point', ['x', 'y', 'z'], defaults=(1,2))
    Point2 = namedtuple('Point', ['x', 'y', 'z'], module="bingo")
    a = Point1(666)
    b = Point2(1,2,3)
    print(a.__module__) # __main__
    print(b.__module__) # bingo
    

注:命名元组实例没有针对每个实例的字典,因此它们是轻量级的,并且不需要比常规元组更多的内存。

实例

>>> # 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)

属性和方法

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

方法

_make()

classmethod somenamedtuple._make(iterable)

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

Point = namedtuple('Point', ['x', 'y'])
t = [11, 22]
Point._make(t)  # Point(x=11, y=22)

_asdict()

somenamedtuple._asdict()

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

>>> p = Point(x=11, y=22)
>>> p._asdict()
{'x': 11, 'y': 22}

_replace(**kwargs)

somenamedtuple._replace(**kwargs)

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

>>> p = Point(x=11, y=22)
>>> p._replace(x=33)
Point(x=33, y=22)

属性

_fields

somenamedtuple._fields

将namedtuple中的键输出成元组的形式,用于自我检查或者从现有的namedtuple中创建新的namedtuple

>>> 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)

_field_defaults

somenamedtuple._field_defaults

将默认的键值对整理成字典的形式

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

其他操作

获取键的值

要获取某个键的值,使用 getattr() 函数 :

>>> p = Point(x=11, y=22)
>>> getattr(p, 'x')
11

将字典转换成namedtuple

转换一个字典到命名元组,使用 ** 两星操作符

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

参考文章

posted @   zlbingo  阅读(70)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示