【问题标题】:Modifying global dictionary in python within a function在函数中修改python中的全局字典
【发布时间】:2014-09-18 06:06:09
【问题描述】:
#!/usr/bin/env python

def modify_dict():

    d['two'] = 2

d = {'one':1}

modify_dict()

print d

我明白了

$ ./globaltest.py 
{'two': 2, 'one': 1}

我希望只看到{'one':1},因为 d 没有在函数中声明为全局的。为什么 d 得到了两个键值对?

【问题讨论】:

  • 因为d 是可变的,并且你在字典内部对d 执行的操作不被视为函数的赋值操作。例如,使用列表(可变对象)+= 运算符将在函数体中引发错误,但 .append 和 .extend 以及按索引分配将正常工作。
  • 扩展 - 当你将 (x = y) 分配给函数内的变量时,python 隐含地决定你指的是本地变量。语法 d[k] = x 解析为 __setitem__ 调用 - 所以虽然它在语法上看起来像赋值,但它不是。

标签: python


【解决方案1】:

看看python的data model。字典和列表是可变对象,这就是为什么全局定义的字典不需要声明为global。它们的内容可能随时更改。

要理解可变性,请考虑 python 中的字符串。它们是一个 不可变 对象。例如,您可以替换给定字符串的内容,但在这样做时,解释器会创建一个新的字符串对象,从而为该字符串对象赋予一个新的标识(因此是一个内存地址)。

>>> s = "foo"
>>> id(s)
140202745404072
>>> s = "bar"
>>> id(s)
140202745404112

我以前回答过a fewsimilar 的问题,所以看看你是否能从他们那里找到更多信息。

【讨论】:

    【解决方案2】:

    快速解决方法是在函数的本地范围内复制字典。

    import copy
    
    d = {'one':1}
    
    def modify_dict():
        local_d = copy.deepcopy(d)
        local_d['two'] = 2
        print local_d
    
    modify_dict()
    print d
    

    您将看到以下输出:

    >>>{'two': 2, 'one': 1}
    >>>{'one': 1}
    

    【讨论】:

      【解决方案3】:

      Python 搜索变量是基于LEGB 规则:

      Local, Enclosing functions, Global, Built-in
      

      当您调用函数时,它会尝试查找名为 d 的变量,并且会在全局范围内查找,因为您在调用函数之前创建了 d。而且由于 d 是可变的,它会被更新。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-02-16
        • 2015-10-04
        • 1970-01-01
        • 2014-06-19
        • 2022-10-04
        • 2011-11-19
        • 2020-06-28
        相关资源
        最近更新 更多