【问题标题】:Using lambda and defaultdict使用 lambda 和 defaultdict
【发布时间】:2018-07-11 13:14:40
【问题描述】:

我正在阅读有关集合 defaultdict 并遇到以下代码行:

import collections
tree = lambda: collections.defaultdict(tree)
some_dict = tree()
some_dict['colours']['favourite'] = "yellow"

我知道lamba 接受一个变量并对其执行一些功能。我见过像这样使用 lambda: λx:x + 3 上面第二行代码中,lambda 取的是什么变量,执行的是什么函数?

我也明白 defaultdict 可以带 int 或 list 等参数。在第二行中,defaultdict 采用参数树,它是一个变量。这有什么意义?

【问题讨论】:

  • 它不带参数,它只是一个不带参数的函数。

标签: python lambda defaultdict


【解决方案1】:

代码大致相当于(忽略def语句引入的元数据)

import collections
def tree():
    return collections.defaultdict(tree)
some_dict = tree()
some_dict['colours']['favourite'] = "yellow"

lambda 表达式简单地定义了一个零参数的函数,并且该函数与名称tree 绑定。

通常,只有在您真正需要匿名函数时才使用lambda 表达式,例如将其作为参数传递给另一个函数,如下所示

sorted_list = sorted(some_list_of_tuples, key=lambda x: x[0])

当您真正想要一个命名函数时,使用def 语句被认为是更好的做法。


defaultdict 需要一个可调用对象,用于为新键生成默认值。 int() 返回 0,list() 返回一个空列表,tree() 返回一个新的defaultdict;它们都可以用作defaultdict 的参数。定义tree 以返回defaultdict 的递归性质,使用自身作为默认值生成器,这意味着您可以生成任意深度的嵌套字典;每个“叶子”字典本身就是另一个 defaultdict

【讨论】:

    【解决方案2】:

    上面第二行代码中,lambda取了什么变量,执行了什么函数?

    lambda 函数是一个匿名(无名称)函数。所以像这样的 lambda 表达式:

    tree = lambda: collections.defaultdict(tree)
    

    是,除了一些细节(事实上它的__name__属性包含函数的名称,而不是'<lambda>'),它等价于:

    def tree():
        return collectsions.defaultdict(tree)
    

    因此,与简单表达式的不同之处在于,我们在这里将计算编码为一个函数。我们永远不能调用它,调用一次或多次。

    它还允许我们打结。请注意,我们在结果中传递了对函数(lambda 表达式)的引用。因此,我们有一个构造 defaultdict 的函数,并将函数本身作为工厂。因此我们可以递归地构造子树。

    我也明白defaultdict可以带intlist等参数。在第二行中,defaultdict 采用参数树,它是一个变量。这有什么意义?

    因此,我们传递给defaultdicttree 是对我们构造的lambda 表达式的引用。因此,这意味着如果defaultdict 调用“工厂”。我们又得到了另一个defaultdict,工厂又是tree

    如果我们因此调用some_dict['foo']['bar']['qux']。因此,我们在defaultdict 中有一个defaultdict 在一个defaultdict 中。所有这些defaultdicts 出厂时都具有tree 功能。如果我们稍后构造额外的孩子,这些将再次成为 defaultdicttree 作为构造函数。

    listint 的情况并不特殊。如果您调用list(如list()),那么您将构造一个new 空列表。 int 也是如此:如果你调用int(),你将获得0。这是对类对象的引用这一事实无关紧要:defaultdict 没有考虑到这一点(它不知道工厂是什么,它只在没有参数的情况下调用它)。

    【讨论】:

    • 非常感谢您的详细解释。那么上面的代码可以让你在每次添加层的时候通过创建一个新的defaultdict来创建一个无限嵌套的字典?
    • @Anya:是的,但你当然不会立即创建它。更重要的是,每次你得到一个项目,比如some_dict[''foo']foo 丢失时,你调用tree,这将因此再次构造一个defaultdicttree 作为工厂。但你确实可以在这个some_dict 中任意深入。
    猜你喜欢
    • 2012-01-15
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-29
    • 2017-04-05
    • 2023-03-26
    相关资源
    最近更新 更多