Python 将iterable解包为其他iterable?

Python 将iterable解包为其他iterable?,python,python-3.x,iterable-unpacking,Python,Python 3.x,Iterable Unpacking,在从ASCII文件读取数据时,我发现自己在做如下工作: (a, b, c1, c2, c3, d, e, f1, f2) = (float(x) for x in line.strip().split()) c = (c1, c2, c3) f = (f1, f2) 如果我每行有一定数量的元素(我确实有),并且只有一个要解包的多元素条目,我可以使用类似于`(a,b,*c,d,e)=……'()的东西 即使我没有,我当然可以用星号组件替换上面示例中的两个多元素条目中的一个:(a,b,*c,d,e,

在从ASCII文件读取数据时,我发现自己在做如下工作:

(a, b, c1, c2, c3, d, e, f1, f2) = (float(x) for x in line.strip().split())
c = (c1, c2, c3)
f = (f1, f2)
如果我每行有一定数量的元素(我确实有),并且只有一个要解包的多元素条目,我可以使用类似于`(a,b,*c,d,e)=……'()的东西

即使我没有,我当然可以用星号组件替换上面示例中的两个多元素条目中的一个:
(a,b,*c,d,e,f1,f2)=……

据我所知,
itertools
在这里不是立即可用的

除了上面的三行代码之外,还有其他可能被认为是“更具Python风格”的代码吗?原因我可能不知道


它是确定的,但每行仍然不同,模式对于
numpy
s函数
loadtxt
genfromtxt
来说太复杂了,为什么不直接切片一个元组呢

t = tuple(float(x) for x in line.split())
c = t[2:5]  #maybe t[2:-4] instead?
f = t[-2:]
演示:


当我们谈到pythonic时,
line.strip().split()
总是可以安全地写成
line.split()
,其中
line
是一个字符串<代码>拆分将在您不给它任何参数时为您去除空白。

如果您确实经常使用此类语句,并且希望代码具有最大的灵活性和可重用性,而不是经常编写此类模式,我建议为其创建一个小函数。只需将其放入某个模块并导入即可(您甚至可以导入我创建的脚本)

有关用法示例,请参见
if\uuuuu name\uuuuu==“\uuuuu main\uuuuu”
块。诀窍是使用组ID列表将
t
的值分组在一起。此id列表的长度应至少与
t
的长度相同

我只解释主要概念,如果你什么都不懂,就问吧

我使用itertools中的
groupby
。尽管在这里如何使用它可能并不简单,但我希望它能很快被理解

作为
-函数,我使用通过工厂函数动态创建的方法。这里的主要概念是“闭包”。组ID列表正“附加”到内部函数
get\u group
。因此:

  • 该列表特定于对
    extract\u groups\u from\u iterable
    的每次调用。您可以多次使用它,不使用全局变量

  • 此列表的状态在对同一个
    get\u group
    实例的后续调用之间共享(请记住:函数也是对象!因此在脚本执行期间,我有两个
    get\u group
    实例

除此之外,我还有一个简单的方法,可以从
groupby
返回的组中创建列表或标量

就这样

from itertools import groupby

def extract_groups_from_iterable(iterable, group_ids):
    return [_make_list_or_scalar(g) for k, g in 
                        groupby(iterable, _get_group_id_provider(group_ids))
           ]

def _get_group_id_provider(group_ids):
    def get_group(value, group_ids = group_ids):
        return group_ids.pop(0)
    return get_group

def _make_list_or_scalar(iterable):
    list_ = list(iterable)
    return list_ if len(list_) != 1 else list_[0]

if __name__ == "__main__":
    t1 = range(9)
    group_ids1 = [1,2,3,4,5,5,6,7,8]
    a,b,c,d,e,f,g,h = extract_groups_from_iterable(t1, group_ids1)

    for varname in "abcdefgh":
        print varname, globals()[varname]

    print

    t2 = range(15)
    group_ids2 = [1,2,2,3,4,5,5,5,5,5,6,6,6,7,8]
    a,b,c,d,e,f,g,h = extract_groups_from_iterable(t2, group_ids2)

    for varname in "abcdefgh":
        print varname, globals()[varname]
输出为:

a 0
b 1
c 2
d 3
e [4, 5]
f 6
g 7
h 8

a 0
b [1, 2]
c 3
d 4
e [5, 6, 7, 8, 9]
f [10, 11, 12]
g 13
h 14

再一次,这似乎有些过分,但如果这有助于减少代码,请使用它。

添加了python-3.0x标记,因为pep3132(可扩展的iterable解包)是在python 3.0及更高版本上实现的。实际上,我有7个不同的元素,所以我需要执行
a,b,c,d=t[:4];e=t[4:6];f,g,h=t[6:9]
…不确定这是否是一种改进。也许是。
a 0
b 1
c 2
d 3
e [4, 5]
f 6
g 7
h 8

a 0
b [1, 2]
c 3
d 4
e [5, 6, 7, 8, 9]
f [10, 11, 12]
g 13
h 14