groupby我正在检查Python中toolz库函数的代码,我发现了这个:
def groupby(key, seq):
""" Group a collection by a key function
"""
if not callable(key):
key = getter(key)
d = collections.defaultdict(lambda: [].append)
for item in seq:
d[key(item)](item)
rv = {}
for k, v in d.items():
rv[k] = v.__self__
return rv
Run Code Online (Sandbox Code Playgroud)
有什么理由使用rv[k] = v.__self__而不是rv[k] = v?
Meg*_*Ing 40
这是一个有点令人困惑的技巧,可以节省少量时间:
我们正在创建一个带有工厂函数的工厂函数,该函数返回带有 的新列表实例的defaultdict绑定方法。然后我们就可以这样做,而不是像创建一个包含列表的那样。如果我们不每次都查找,我们就会赢得一点时间。append[].appendd[key(item)](item)d[key(item)].append(item)defaultdictappend
但现在dict包含绑定方法而不是列表,因此我们必须通过 获取原始列表实例__self__。
__self__是为返回原始实例的实例方法描述的属性。您可以使用以下示例验证这一点:
>>> a = []
>>> a.append.__self__ is a
True
Run Code Online (Sandbox Code Playgroud)
Mad*_*ist 18
这是一种有点复杂但可能更有效的创建和使用defaultdict。
首先,请记住默认项目是lambda: [].append。这意味着创建一个新列表,并将绑定append方法存储在字典中。这可以节省您在每次进一步追加到同一键时的方法绑定,以及随后的垃圾收集。例如,以下更标准的方法效率较低:
d = collections.defaultdict(list)
for item in seq:
d[key(item)].append(item)
Run Code Online (Sandbox Code Playgroud)
那么问题就变成了如何从字典中获取原始列表,因为引用没有显式存储。幸运的是,绑定方法有一个__self__属性可以做到这一点。这里,[].append.__self__是对原文的引用[]。
作为旁注,最后一个循环可能是一个理解:
return {k: v.__self__ for k, v in d.items()}
Run Code Online (Sandbox Code Playgroud)