You are here:  Home » Python » defaultdict对象-collections- 容器数据类型(30)Python语言(必读进阶学习教程)(参考资料)

class collections.defaultdictdefault_factory [… 
返回一个新的类字典对象。 defaultdict是内置类的子dict类。它会覆盖一个方法并添加一个可写实例变量。其余功能与dict课程相同, 此处未记录。

第一个参数提供default_factory 属性的初始值; 它默认为None。所有剩余的参数都被视为传递给dict构造函数,包括关键字参数。

defaultdict除标准dict操作外,对象还支持以下方法:

__missing__关键
如果default_factory属性为NoneKeyError则以为参数引发 异常。

如果default_factory不是None,则在没有参数的情况下调用它来为给定提供默认值,将该值插入的字典中并返回。

如果调用default_factory引发异常,则会异常传播此异常。

当找不到请求的密钥时,该__getitem__()方法由dict类的方法 调用; 无论它返回或加注,然后返回或提高__getitem__()

请注意,除了之外的任何操作__missing__()不会调用 __getitem__()。这意味着get(),与普通词典一样,它将None作为默认值返回而不是使用 default_factory

defaultdict 对象支持以下实例变量:

default_factory
该属性由__missing__()方法使用; 它从构造函数的第一个参数初始化(如果存在),或者None如果不存在则初始化 。

defaultdict示例

使用listas default_factory,很容易将一系列键值对分组到列表字典中:

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
...     d[k].append(v)
...
>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

 

当第一次遇到每个密钥时,它还没有在映射中; 所以使用default_factory 返回空的函数自动创建一个条目listlist.append() 然后,该操作将值附加到新列表。当再次遇到密钥时,查找会正常进行(返回该密钥的列表),然后 list.append()操作会向列表中添加另一个值。这种技术比使用dict.setdefault()以下技术的等效技术更简单,更快捷:

>>> d = {}
>>> for k, v in s:
...     d.setdefault(k, []).append(v)
...
>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

 

设置default_factoryto int使 defaultdict计数有用(如其他语言的包或多重集):

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
...     d[k] += 1
...
>>> sorted(d.items())
[('i', 4), ('m', 1), ('p', 2), ('s', 4)]

 

首次遇到字母时,映射中缺少该字母,因此 default_factory函数调用int()以提供默认计数为零。然后,递增操作会为每个字母构建计数。

int()始终返回零的函数只是常量函数的特例。创建常量函数的更快更灵活的方法是使用lambda函数,它可以提供任何常量值(而不仅仅是零):

>>> def constant_factory(value):
...     return lambda: value
>>> d = defaultdict(constant_factory('<missing>'))
>>> d.update(name='John', action='ran')
>>> '%(name)s %(action)s to %(object)s' % d
'John ran to <missing>'

 

设置default_factoryto set使得 defaultdict构建集合字典非常有用:

>>> s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
>>> d = defaultdict(set)
>>> for k, v in s:
...     d[k].add(v)
...
>>> sorted(d.items())
[('blue', {2, 4}), ('red', {1, 3})]

 

namedtuple()具有命名字段的元组的工厂函数

命名元组为元组中的每个位置赋予含义,并允许更可读,自我记录的代码。它们可以在使用常规元组的任何地方使用,并且它们添加了按名称而不是位置索引访问字段的功能。

collections.namedtupletypenamefield_names*rename = Falsedefaults = Nonemodule = None 
返回名为typename的新元组子类。新子类用于创建类似元组的对象,这些对象具有可通过属性查找访问的字段以及可索引和可​​迭代的字段。子类的实例也有一个有用的docstring(带有typename和field_names)和一个有用的__repr__() 方法,它以一种name=value格式列出元组内容。

FIELD_NAMES是字符串如序列。或者,field_names可以是单个字符串,每个字段名由空格和/或逗号分隔,例如或。['x', 'y']'x y''x, y'

除了以下划线开头的名称外,任何有效的Python标识符都可用于字段名。有效标识符由字母,数字和下划线,但不以数字或下划线开始,不能是keyword诸如回报全球通过,或提高

如果重命名为true,则无效的字段名称将自动替换为位置名称。例如,转换为,删除关键字 和重复的fieldname 。['abc', 'def', 'ghi', 'abc']['abc', '_1', 'ghi', '_3']defabc

默认值可以是None或可以迭代的默认值。由于具有默认值的字段必须位于没有默认值的任何字段之后,因此默认值将应用于最右侧的参数。例如,如果字段名是和默认值 ,则将是必需参数,默认为 ,默认为。['x','y', 'z'](1, 2)xy1z2

如果定义了module__module__,则将命名元组的属性设置为该值。

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

在3.1版中更改:添加了对重命名的支持。

改变在3.6版本:冗长重命名参数成为 唯一的关键字参数

版本3.6中已更改:添加了模块参数。

版本3.7中已更改:删除详细参数和_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)

 

命名元组对于将字段名称分配给由csvsqlite3模块返回的结果元组特别有用:

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._makeiterable 
从现有序列生成新实例或可迭代的类方法。

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

 

somenamedtuple._asdict
返回一个新的OrderedDict映射字段名称到它们对应的值:

>>> 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._fields_defaults
字典将字段名称映射到默认值。

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

 

要检索名称存储在字符串中的字段,请使用以下getattr() 函数:

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

 

要将字典转换为命名元组,请使用double-star-operator(如Unpacking Argument Lists中所述):

>>> 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中更改:属性docstrings变得可写。

可以使用_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')

 

也可以看看

  • 由Jan Kaliszewski编写的带有元类混合的命名元组抽象基类的配方。除了为命名元组提供抽象基类之外,它还支持基于元类的备用构造函数,该构造函数便于将子元素命名为元组的用例。
  • 请参阅types.SimpleNamespace()基于底层字典而不是元组的可变命名空间。
  • 有关typing.NamedTuple()为命名元组添加类型提示的方法,请参阅参考资料。