从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)= .. 。(Extended iterable unpacking)。
即使我不这样做,我当然也可以用星号组件(a, b, *c, d, e, f1, f2) = ...
替换上面例子中的两个多元素条目的一个。
据我所知,itertools
在这里没有立即使用。
上面的三行代码有什么替代品可能被认为是“更加pythonic”的原因我可能不知道吗?
¹确定但仍然每行变化,对于numpy
函数loadtxt
或genfromtxt
,模式过于复杂。
答案 0 :(得分:1)
如果您经常使用这些语句,并且希望代码具有最大的灵活性和可重用性,而不是经常编写这样的模式,那么我建议为它创建一个小函数。只需将其放入某个模块并导入它(您甚至可以导入我创建的脚本)。
有关用法示例,请参阅if __name__=="__main__"
块。诀窍是使用组ID列表将t
的值组合在一起。此ID列表的长度应至少与t
的长度相同。
我只会解释主要概念,如果你什么都不懂,那就问问。
我使用itertools中的groupby
。尽管如何在这里使用它可能并不简单,但我希望它很快就可以理解。
作为key
- 函数我使用通过工厂函数动态创建的方法。这里的主要概念是“闭包”。组ID列表正在“附加”到内部函数get_group
。因此:
该列表特定于每次调用extract_groups_from_iterable
。您可以多次使用它,不使用全局变量
此列表的状态在对同一get_group
实例的后续调用之间共享(请记住:函数也是对象!所以我在执行期间有两个get_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
再一次,这看起来有点矫枉过正,但如果这有助于您减少代码,请使用它。
答案 1 :(得分:0)
为什么不切片一个元组?
t = tuple(float(x) for x in line.split())
c = t[2:5] #maybe t[2:-4] instead?
f = t[-2:]
演示:
>>> line = "1 2 3 4 5 6 7 8 9"
>>> t = tuple(float(x) for x in line.split())
>>> c = t[2:5] #maybe t[2:-4] instead?
>>> f = t[-2:]
>>> c
(3.0, 4.0, 5.0)
>>> t
(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0)
>>> c = t[2:-4]
>>> c
(3.0, 4.0, 5.0)
虽然我们的主题是pythonic,但line.strip().split()
始终可以安全地写为line.split()
,其中line
是一个字符串。当你没有给出任何论据时,split
会为你删除空白。