namedtuple工厂函数,创造一个像实例对象的元祖(感觉到了Python的奇妙与可爱之处)。

Posted 区块链散户一枚

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了namedtuple工厂函数,创造一个像实例对象的元祖(感觉到了Python的奇妙与可爱之处)。相关的知识,希望对你有一定的参考价值。

发现了namedtuple将大大的方便对象实例化的过程,底层我觉的应该应用了描述符的相关指令__set__,__get__,__delete__等等,深的不讲了,我给自己记号一下如何把这个函数用好。

 

基本概念

  1. namedtuple是一个 工厂函数,定义在python标准库的collections模块中,使用此函数可以创建一个可读性更强的元组
  2. namedtuple函数所创建(返回)的是一个 元组的子类(python中基本数据类型都是类,且可以在buildins模块中找到)
  3. namedtuple函数所创建元组,中文名称为 具名元组
  4. 在使用普通元组的时候,我们只能通过index来访问元组中的某个数据
  5. 使用具名元组,我们既可以使用index来访问,也可以使用具名元组中每个字段的名称来访问
  6. 值得注意的是,具名元组和普通元组所需要的内存空间相同,所以 不必使用性能来权衡是否使用具名元组

if sys.version_info >= (3, 7):
    def namedtuple(typename: str, field_names: Union[str, Iterable[str]], *,
                   rename: bool = ..., module: Optional[str] = ..., defaults: Optional[Iterable[Any]] = ...) -> Type[tuple]: ...
elif sys.version_info >= (3, 6):
    def namedtuple(typename: str, field_names: Union[str, Iterable[str]], *,
                   verbose: bool = ..., rename: bool = ..., module: Optional[str] = ...) -> Type[tuple]: ...
else:
    def namedtuple(typename: str, field_names: Union[str, Iterable[str]],
                   verbose: bool = ..., rename: bool = ...) -> Type[tuple]: ...

进去源码里面可以看到,应该当Python的版本不同时,里面的默认参数也会不同,我是3.7的,我看的数版本肯定不是3.7的,所以介绍的里面不全。

第一个参数:typename是调用namedtuple函数时作为新创建的类名称。

第二个参数:field_names可以传入str或者可迭代的对象的str[\'color\',\'age\']类似这种,或者字符串\'color age\'属性之间必须空格,内部应该执行了split命令,还有就是里面的str不能是Python里面的关键字,比如def,class。

后面的参数书上没介绍,网上找来部分资料。

rename

  • 注意的参数中使用了*,其后的所有参数必须指定关键字
  • 参数为布尔值
  • 默认为False。当我们指定为True时,如果定义field_names参数时,出现非法参数时,会将其替换为位置名称。如[\'abc\', \'def\', \'ghi\', \'abc\']会被替换为[\'abc\', \'_1\', \'ghi\', \'_3\']

defaults

  • 参数为None或者可迭代对象
  • 当此参数为None时,创建具名元组的实例时,必须要根据field_names传递指定数量的参数
  • 当设置defaults时,我们就为具名元组的元素赋予了默认值,被赋予默认值的元素在实例化的时候可以不传入
  • defaults传入的序列长度和field_names不一致时,函数默认会右侧优先
  • 如果field_names[\'x\', \'y\', \'z\']defaults(1, 2),那么x是实例化必填参数,y默认为1z默认为2
上代码。
from collections import namedtuple

Car = namedtuple(\'Car\', \'color brand def\', rename=True, defaults=(\'red\', \'honda\'))

car = Car(\'temp\')        # 初始化实例,由于前面已经有了两个默认值,就填写了少的一个
print(car)               # 输出实现显示格式,Car(color=\'temp\', brand=\'red\', _2=\'honda\')
# 很好玩的默认赋值方式,默认的赋值是从后面往前面自动匹配,因为我最后的是非法字符def
# rename选项打开以后自动转换成字符_2,然后进行赋值
print(car.color)          # 通过.取出属性
print(car[1])             # 通过索引取出属性
print(\'\'.join(car))       # 有着元祖的特性进行内容拼接。
car.color = \'blue\'         # 有着元祖的特性,内部元素不容修改
Traceback (most recent call last):
  File "/Users/shijianzhong/Desktop/bit_coin/test_file/test_namedtuple.py", line 10, in <module>
    car.color = \'blue\'
AttributeError: can\'t set attribute
Car(color=\'temp\', brand=\'red\', _2=\'honda\')
temp
red
tempredhonda

 通过代码显示可以看出,实例出来的对象既有元祖的全部特性,还像一个只读的自定义对象。类似MappingProxyType(实例)

 

namefile还提供了一些游泳的辅助方法。

第一个_fields,用继续另外一个基类元祖的字段。

print(Car._fields)

 

(\'color\', \'brand\', \'_2\')

 直接输出Car的字段,将三个属性输出,所以,如果想继承的话,可以这么写

Car2 = namedtuple(\'Car2\', Car._fields+(\'other\',))

记得上面的参数小括号里面的逗号,因为元祖+元祖才返回一个元祖。
 
 
第二个是_asdict
print(car._asdict())
OrderedDict([(\'color\', \'temp\'), (\'brand\', \'red\'), (\'_2\', \'honda\')])

 生成了一个有序的字典,这样的话,就可以按照字典的方式,随意操作了。

 

第三个是_replace,用来替换里面的参数,返回一个新实例

n_car = car._replace(brand=\'blue\')
print(n_car)

 

Car(color=\'1\', brand=\'blue\', _2=\'temp\')

 这个刚开犯傻了一下,以为是列表没有给予赋值,car自身会发生变换,还是脑子秀逗了,对于元祖的任何操作,跟字符串都一样,因为对象本身是不可变的,所以当有变化发生时,需要变量名来接受修改后的参数。

 

最后一个_make类方法,用来从序列或迭代对象中创建nametuple的新实例。

car2 = Car._make([\'purple\',\'audi\',\'tt\'])
print(car2)

 

Car(color=\'1\', brand=\'blue\', _2=\'temp\')
Car(color=\'purple\', brand=\'audi\', _2=\'tt\')

 

最后的参数链接,作者写的比我详细,大家可以参考学习下。

 
 
 
参考链接:https://www.jianshu.com/p/60e6484a7088

以上是关于namedtuple工厂函数,创造一个像实例对象的元祖(感觉到了Python的奇妙与可爱之处)。的主要内容,如果未能解决你的问题,请参考以下文章

Python3的namedtuple

namedtuple工厂函数精讲

创造型模式-工厂模式1

collections.namedtuple工厂函数

创造型设计模式-----工厂方法模式

常用的JavaScript设计模式Factory(工厂)模式