灵活性问题:索引变量 vs. 常量

3

考虑以下假设情况。

作为您在python中开发的应用程序的一部分,您必须格式化对象列表并将每个后续项分配给提供的关键字作为元组。以下是语法:

entries = [keyword, [obj1, obj2, obj3, ...]]    # Original list of object entries

formatted = [(keyword, obj1), (keyword, obj2), (keyword, obj3), ...]

这里是您提出的函数(如果有更高效的方法,请告诉我):

def format(keyword, entries):
    return [(keyword, x) for x in entries[1][0]]

这是应用该函数的示例:

foo = format(entries[0], entries[1])

灵活性问题

注意,在format函数中,entries变量具有静态索引整数10。假设您预计可能会将新术语附加到entries列表中。您会通常使用索引变量而不是常量(对于稍后将进入列表的项目,您可以期望增加常量),如果使用索引变量,您会使用本地或全局索引吗?您如何在代码中考虑此类灵活性?


2
如果我发现在许多地方使用变量作为这些条目的索引,我会考虑将其制作成一个namedtuple或一个class - satoru
1
另外一个要点:也许你希望 format 一开始就只接受一个参数(然后在内部进行拆分),这样你就可以直接使用 foo = format(entries)。或者,另一种方式是 foo = format(*entries)。不过,如果没有看到更多的基础设施,很难确定最终代码的清晰度如何。 - abarnert
2
请注意,使用 itertools.izip_longest 可以实现 format -- list(itertools.izip_longest([],['foo','bar','baz'],fillvalue='keyword')) -- 大多数情况下您甚至不需要一个列表对象,可迭代对象也很好用 :) - mgilson
1
对于 format(),我认为你的意思是 return [(keyword, x) for x in entries] - martineau
2
@Biff:entries是一个全局变量和一个函数参数,在函数中会使用该参数。 - martineau
显示剩余11条评论
2个回答

4
您正在向函数传递一个关键字和一维列表。为什么在函数定义中要使用索引?按照现有的写法,我得到以下内容。
e = ['spam', ['aa','bb','cc','dd']]

def format(keyword, entries):
    return [(keyword, x) for x in entries[1][0]]

format(e[0], e[1])
[('spam', 'b')]

根据对象的不同,可能会出现索引错误。在函数内部并不需要使用索引。

def format(keyword, entries):
    return [(keyword, x) for x in entries]

format(e[0], e[1])
[('spam', 'aa'), ('spam', 'bb'), ('spam', 'cc'), ('spam', 'dd')]

这个问题已经在评论中由martineau回答了,我没有认真阅读,所以应该给予他应有的荣誉。抱歉。

这个确实让它变得更灵活,因为我们知道索引不是必需品。我认为这是正确的答案,因为你让我意识到了索引并不是必须的。 - Biff
2
这只是展示了如何修复我在评论中提到的问题。 - martineau
我也将使用压缩的 *args 技术。 - Biff
抱歉,martineau,我是新来的,没有看到您的评论。我会相应地编辑我的帖子。 - Jamie Duby
Biff和Jamie:没问题,当有很多活动时事情可能会变得忙碌。欢迎来到StackOverflow。;-) - martineau

1

结合评论中的各种解决方案(Satoru.Logic和mgilson在这里可能比我更值得赞扬):

def format(entries): # no need to split it in the caller
    # consider yield from instead of return in 3.3+
    return itertools.izip_longest([], entries[1][1][0], fill=entries[0])

foo = format(entries)

然而,我不确定你的原始代码是否正确。

当你调用format(entries[0], entries[1])时,那将是format(keyword, [obj1, obj2, obj3, ...])。然后,在format内部,你正在迭代entries[1][0],这意味着obj2[0],忽略了所有其他条目。这似乎不正确。例如,如果obj2实际上是字符串'obj2',那么它就是字���'o'。因此,[(keyword, x) for x in entries[1][0]]将只是[('keyword', 'o')]


我还没有使用过 itertools - 我会研究一下。 - Biff
在Python 3.3+中,“yield from”相对于“return”的优势是什么?我在这里看不出区别(除了“return”可以与早期版本一起使用)。另外,在Python 3中它是“zip_longest”。 - mgilson
这不是yield fromreturn更有优势,而是yield fromyield更有优势,如果你想让format成为一个真正的生成器函数。在大多数情况下,你真的无论如何都不关心,但如果你确实关心,并且你犹豫不决,你可能会说“不,循环和yield太麻烦了”用2.7或3.2,但用3.3就可以说“为什么不呢”。我想我应该在答案中更好地解释一下。 - abarnert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接