【问题标题】:Python empty dict not being passed by reference?Python空字典没有通过引用传递?
【发布时间】:2014-06-04 22:41:12
【问题描述】:

这个示例代码有点奇怪,但请耐心等待......

class Foo(object):
    def __init__(self, internal_dict = None):
        self._internal_dict = internal_dict or {}

        for attribute_name in self.__class__.__dict__.keys():
            attr = getattr(self.__class__, attribute_name)
            if isinstance(attr, str) and attribute_name.startswith("a"):
                # We are iterating over all string attributes of this class whos name begins with "a" 
                self._internal_dict[attribute_name] = {}
                setattr(self, attribute_name + '_nested_object', Foo(internal_dict=self._internal_dict[attribute_name]))

class FooChild(Foo):
    ax = "5"
    ay = "10"

fc = FooChild()

print fc.ax_nested_object._internal_dict # This prints {}

fc.ax_nested_object._internal_dict['123'] = 'abc'

print fc._internal_dict # This prints {'ay': {}, 'ax': {}}

我本来希望我的{'123' = 'abc'} 能够通过第二次打印,因为字典应该通过引用传递到递归__init__ 调用中。但是,如果我更改此行:

self._internal_dict[attribute_name] = {}

到这里:

self._internal_dict[attribute_name] = {'test': 1}

然后我得到以下打印:

{'test': 1}
{'ay': {'test': 1}, 'ax': {'test': 1, '123': 'abc'}}

为什么启动该字典数据会导致它通过引用正确传递?

【问题讨论】:

  • 这就是我让人们在检查是否提供可选参数时询问是否包含is None 的确切原因。感谢您确认这确实发生了 ;-)

标签: python recursion


【解决方案1】:

这就是问题所在:

self._internal_dict = internal_dict or {}

空字典是假的,所以你会在后续的递归调用中得到一个 new 空字典。这就是为什么将 dict 初始化为非空(真实)“修复”它的原因。

你想要:

self._internal_dict = {} if internal_dict is None else internal_dict

【讨论】:

  • 谢谢!我以为我要疯了。
【解决方案2】:

你的类的问题是你分配self._internal_dict变量的捷径。

不幸的是,空字典的真值为 false。

如果您将代码更改为:

class Foo(object):
    def __init__(self, internal_dict = None):
        if internal_dict is None:
            internal_dict = {}

        self._internal_dict = internal_dict

        for attribute_name in self.__class__.__dict__.keys():
            attr = getattr(self.__class__, attribute_name)
            if isinstance(attr, str) and attribute_name.startswith("a"):
                # We are iterating over all string attributes of this class whos name begins with "a" 
                self._internal_dict[attribute_name] = {}
                setattr(self, attribute_name + '_nested_object', Foo(internal_dict=self._internal_dict[attribute_name]))

class FooChild(Foo):
    ax = "5"
    ay = "10"

fc = FooChild()

print fc.ax_nested_object._internal_dict # This prints {}

fc.ax_nested_object._internal_dict['123'] = 'abc'

print fc._internal_dict # This prints {'ay': {}, 'ax': {}}

【讨论】:

    猜你喜欢
    • 2018-04-24
    • 1970-01-01
    • 2017-07-29
    • 2021-10-13
    • 1970-01-01
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多