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

posted @ 2019-11-17 16:27  就是想学习  阅读(319)  评论(0编辑  收藏  举报