Python 用包装代替状态变化,可以按照以下两种策略包装数据。
- 并行:创建两份数据副本,分别对每一份求等级值,然后合并两份副本,得到包含所有等级值的最终结果。这种方式不够简便,因为需要合并顺序不同的两个序列。
- 串行:首先计算出一个变量的等级值,将原始数据包在其中,然后对包装后的数据中的另一个变量再求一次等级值。以这种方式生成的结构会比较复杂,但通过对最后结果做平铺处理可以缓解这个问题。
下面的函数创建了包含y
值等级顺序的包装对象:
from typing import NamedTuple
class Ranked_Y(NamedTuple):
r_y: float
raw: Pair
def rank_y(pairs: Iterable[Pair]) -> Iterable[Ranked_Y]:
return (
Ranked_Y(rank, data)
for rank, data in rank(pairs, lambda pair: pair.y)
)
这里定义了一个包含y
等级值以及原始数据的命名元组。rank_y()
函数通过应用rank()
函数创建了这个元组的实例,而rank()
函数中使用了一个从Pair
对象中提取y
属性的匿名函数,最后得到了二元组实例。
因此当有如下输入时:
>>> data = (Pair(x=10.0, y=8.04),
... Pair(x=8.0, y=6.95),
... Pair(x=13.0, y=7.58),
etc.
... Pair(x=5.0, y=5.68))
输出会如下所示:
>>> list(rank_y(data))
[Ranked_Y(r_y=1.0, raw=Pair(x=4.0, y=4.26)),
Ranked_Y(r_y=2.0, raw=Pair(x=7.0, y=4.82)),
Ranked_Y(r_y=3.0, raw=Pair(x=5.0, y=5.68)),
etc.
Ranked_Y(r_y=11.0, raw=Pair(x=12.0, y=10.84))]
将原来的Pair
对象包装进了包含等级值的新Ranked_Y
对象中,但这不是我们想要的。在此基础上需要再次包装,得到包含x
和y
等级值的对象。