collections
模块不太常用,之前我也从未接触过,最近在看EfficientNet
的源码发现程序中作者用了collections.namedtuple
方法,于是help
了一下查看官方说明文档:
>>> import collections
>>> help(collections.namedtuple)
Help on function namedtuple in module collections:
namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
Returns a new subclass of tuple with named fields.
>>> Point = namedtuple('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
>>> p._replace(x=100) # _replace() is like str.replace() but targets named fields
Point(x=100, y=22)
下面我们一步步分析这些操作:
官方说明namedtuple
的下面一句话即Returns a new subclass of tuple with named fields.
说的是该函数的作用是什么,即返回具有命名字段的元组的新子类。这是啥意思呢?其实就是定义一个元组子类,那么这个子类的类名为参数typename
,这个子类具有若干个名命字段即field_names
中的若干个元素,这些名命字段共同构成一个元组,当然每个名命字段也是这个类的属性。
1.Point = namedtuple('Point', ['x', 'y'])
:类名为Point
,['x', 'y']
为名命字段,'x'
和'y'
构成一个元组,注意类名必须和typename
一致。
2. p = Point(11, y=22)
:初始化类的构造函数,即初始化对象p
,同时给元组中的每个元素赋初值。
3. 此时p
为元组对象,既可以用下标索引也可以用点来访问对象属性即元组中的元素p[0] + p[1]
、p.x + p.y
4. 可以通过_replace()
方法替换属性的值p._replace(x=100)
5. p._fields
:返回一个元组(包含所有属性)
>>> p._fields
('x', 'y')
另外,如果不想立刻给所有属性赋初始值,可以不用声明对象,直接给所有元素赋相同的初值:
Point = namedtuple('Point', ['x', 'y'])
>>> Point.__new__.__defaults__ = (None, ) * len(Point._fields)
Point.__new__.__defaults__
指的是所有元素的初始值。