像元组也像类的namedtuple

namedtuple是一个函数,其返回值的的行为很像tuple,若要使用它,需要从collections模块中引入,官方文档里说的清楚,namedtuple返回的是tuple的子类,与tuple的不同之处在于,它有属性字段,这使得它看起来,又很像类。下面是一段简单的示例代码

Point = namedtuple("Point", 'x, y')
# Point = namedtuple("Point", 'x y')
# Point = namedtuple("Point", ['x', 'y'])
p = Point(3, 4)
print(p.x, p.y)     # 3, 4
print(issubclass(Point, tuple))   # True

Point的行为,非常像一个类,被注释掉的两行代码具有同样的效果。与普通类创建出来的对象相比,有一处明显不同,你不能修改x和y的值,代码p.x = 8 会引发异常。

初次见到这个类,感到非常的困惑,它和类相比,有什么优势么,既然已经有了类,何必再弄出namedtuple这个看起来不伦不类的东西呢!

我虽然知道,它的属性是不可更改的,但一直没有找到合适的应用场景,直到最近阅读pip的源码,恰好看到了namedtuple的使用。

pip源码里,设计了一个CommandInfo,定义如下

CommandInfo = namedtuple('CommandInfo', 'module_path, class_name, summary')

它是如何被使用的呢?当你在终端里输入pip命令,或者pip help命令时,pip会输出pip相关的所有子命令说明,这些信息,就是用CommandInfo来存储的

commands_dict = OrderedDict([
    ('install', CommandInfo(
        'pip._internal.commands.install', 'InstallCommand',
        'Install packages.',
    )),
    ('download', CommandInfo(
        'pip._internal.commands.download', 'DownloadCommand',
        'Download packages.',
    )),
    ...
    ('help', CommandInfo(
        'pip._internal.commands.help', 'HelpCommand',
        'Show help for commands.',
    )),

OrderedDict可以保证按照定义时的顺序输出命令,CommandInfo是namedtuple创建的,它的三个属性module_path, class_name,summary都是不可更改的,使用namedtuple正好合适。

如果使用类,也可以描述并存储这些信息,但是普通类的属性可以被修改,定义一个属性不可被修改的类也并非不可以,但是那样就不如直接使用namedtuple。

这是我第一次见到的使用namedtuple的项目,在具体的案例场景里,的确可以有更深刻的体会。

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案