python语言基础-4 常用模块-4.12 namedtuple(名称元组)
声明:本内容非盈利性质,也不支持任何组织或个人将其用作盈利用途。本内容来源于参考书或网站,会尽量附上原文链接,并鼓励大家看原文。侵删。
4.12 namedtuple(名称元组)
名称元组是python中提供的一种高级数据类型。它兼具了元组和字典的一些特征,在一些特定场景下十分好用。
4.12.1 元组与字典的缺点(原文链接:https://zhuanlan.zhihu.com/p/266712505)
不同的场景适用不同的数据类型,没有数据类型是绝对完美的。元组与字典也有一些缺点。
如果我们要使用RGBA空间表示颜色,可以使用元组:
# 定义一个根据颜色字符串返回RGBA值的函数
def convert_string_to_color(desc: str, alpha: float = 0.0):if desc == "green":return 50, 205, 50, alphaelif desc == "blue":return 0, 0, 255, alphaelse:return 0, 0, 0, alpha# 正常情况下我们应该这样使用它
r, g, b, a = convert_string_to_color(desc="blue", alpha=1.0)# 但是在不知道函数内部结构的情况下,可能会这样调用。显然,得到的值是错的
a, r, g, b = convert_string_to_color(desc="blue", alpha=1.0)# 在不知道返回值个数或真的只需要其中某几个值时,这样调用将会报错(一个是可以的但会返回整个元组,多于一个但又不足全部时会报错):
r, g, b = convert_string_to_color(desc="blue", alpha=1.0)
也就是说,使用元组这种类型,无法保证值的顺序,并且无法部分获取值。
如果我们使用字典改写以上示例:
# 定义一个根据颜色字符串返回RGBA值的函数
def convert_string_to_color(desc: str, alpha: float = 0.0):if desc == "green":return {"r": 50, "g": 205, "b" :50, "alpha": alpha}elif desc == "blue":return {"r": 0, "g": 0, "b": 255, "alpha": alpha}else:return {"r": 0, "g": 0, "b": 0, "alpha": alpha}# 这时我们可以这样接收返回值,并且返回值将会明确将值与名称对应{'r': 0, 'g': 0, 'b': 255, 'alpha': 1.0}
color = convert_string_to_color(desc="blue", alpha=1.0)# 但是字典类型有两个缺点,一是不方便使用collections.Counter(color)对原色数时行分类统计
num_dict = collections.Counter(color)
print(num_dict) # 输出结果为 Counter({'b': 255, 'alpha': 1.0, 'r': 0, 'g': 0}),并没有输出各rgba值的数量# 二是字典类型是一种可变类型,字典类型的结果容易被误操作
color['type'] = 'm'
color.pop('r') # 如果不小心添加了元素或删除了元素可能会影响后续使用
综上可知,字典类型部分解决了元组类型的缺点,但它本身也有一些新的缺点。
解决这些问题的办法就是使用名称元组(namedtuple)。
4.12.2 namedtuple数据类型的使用
python中有两个模块都提供了namedtuple类型的使用方式。分别是collections模块下的namedtuple和typing模块下的NamedTuple。
使用名称元组类型重新定义以上示例:
# 定义一个根据颜色字符串返回RGBA值的函数,使用collections模块下的namedtuple
from collections import namedtuple
...
Color = namedtuple("Color", "r g b alpha") # 创建Color类型为namedtuple类型的子类型
...
def convert_string_to_color(desc: str, alpha: float = 0.0):if desc == "green":return Color(r=50, g=205, b=50, alpha=alpha)elif desc == "blue":return Color(r=50, g=0, b=255, alpha=alpha)else:return Color(r=50, g=0, b=0, alpha=alpha)# 调用
color = convert_string_to_color(desc="blue", alpha=1.0) # print(color)返回值为Color(r=50, g=0, b=255, alpha=1.0)# 也可以像字典那样很方便地取出其中的某个元素
has_alpha = color.alpha# 允许使用collections.Counter(color)统计
num = collections.Counter(color)
print(num) # 打印结果为Counter({50: 1, 0: 1, 255: 1, 1.0: 1})# 不可轻易改变的数据结构
color.e = 0 # 会报错# 同样我们可以使用typing模块下的NamedTuple来定义
from typing import NamedTuple# 定义Color类型继承NamedTuple类型
class Color(NamedTuple):r: float # 可以限定属性的类型g: floatb: floatalpha: floatdef convert_string_to_color(desc: str, alpha: float = 0.0):if desc == "green":return Color(r=50, g=205, b=50, alpha=alpha)elif desc == "blue":return Color(r=50, g=0, b=255, alpha=alpha)else:return Color(r=50, g=0, b=0, alpha=alpha)# 一样的调用方式
color = convert_string_to_color(desc="blue", alpha=1.0)
print(color.r)
4.12.3 namedtuple与元组和字典的类型转换(原文链接:https://zhuanlan.zhihu.com/p/266712505)
可以很容易地将元组或字典转换为namedtuple类型:
# 将已有的字典值转换为namedtuple(使用typing模块下的NamedTuple)
from typing import NamedTupleclass Color(NamedTuple):r: floatg: floatb: floatalpha: floatc = {"r": 50, "g": 205, "b": 50, "alpha": 1.0}
color = Color(**c) # 只要使用**解包字典类型的变量赋值给Color类型即可
print(color)# 将已有的字典值转换为namedtuple(使用collections模块下的namedtuple)
from collections import namedtuple
...
Color = namedtuple("Color", "r g b alpha")
...c = {"r": 50, "g": 205, "b": 50, "alpha": 1.0}
Color(**c)
print(color)# 也可以直接从一个字典值创建namedtuple类型(使用collections模块下的namedtuple)
from collections import namedtuplec = {"r": 50, "g": 205, "b": 50, "alpha": 1.0}
Color = namedtuple("Color", c) # 由字典值创建Color类型为namedtuple的子类型
color = Color(**c) # 解包字典以创建实例
print(color)# 元组值转namedtuple也是可以的,但无法通过元组创建类型(使用typing模块下的NamedTuple)
from typing import NamedTupleclass Color(NamedTuple):r: floatg: floatb: floatalpha: floatc = (50, 250, 50, 1.0)
color = Color(*c) # 解包时使用*即可
print(color)# 元组值转namedtuple也是可以的,但无法通过元组创建类型(使用collections模块下的namedtuple)
from collections import namedtupleColor = namedtuple("Color", "r g b alpha")
c = (50, 250, 50, 1.0)
color = Color(*c) # 解包时使用*即可
print(color)
namedtuple类型也可以很方便地转为元组或字典类型:
# namedtuple转字典:namedtuple中提供了相关的方法可以直接转为字典类型,而不必逐个添加键值(注意无论是使用typing.NamedTuple定义的Color还是collections.namedtuple定义的Color都是可以使用的)
blue = Color(r=0, g=0, b=255, alpha=1.0)
blue._asdict()# namedtuple转元组:可以直接使用tuple()方法进行转换
tuple(Color(r=50, g=205, b=50, alpha=0.1))