gpt4 book ai didi

python - 字典的 GAE NDB PickleProperty : new entity taking old property?

转载 作者:太空宇宙 更新时间:2023-11-04 03:37:18 25 4
gpt4 key购买 nike

对我来说看起来像是一个错误,但也许有人对此有一个合理的解释。考虑以下代码:

class Test(ndb.Model):
a= ndb.IntegerProperty()
p = ndb.PickleProperty(default={})

现在执行以下操作:

>> t1 = Test()
>> t1.p['a'] = 1
>> t1.p['b'] = 2
{'a': 1, 'b': 2}

到目前为止,一切都很好。但是现在:

>> t2 = Test()
>> t2.p
{'a': 1, 'b': 2}

全新的 t2 实例已被分配了 t1 的 p 值?!!

除了错误之外还有什么解释吗?请注意,执行 t1 的 put() 不会改变行为。

最佳答案

在 Python 中,默认参数被计算一次——因此您使用的是单个 dict(您的default={ } 是每个进程一个字典,而不是每个实体一个!)跨越所有 Test 类型的实体,它们恰好在同一进程中,并且 p 未明确设置。

如果您执行 t=Test(p={}),那么 t 会很好,它有自己的 dict。如果您先执行 t=Test(),然后执行 t.p = {},您也可以。但是,如果您不以某种方式设置实体的特定 p,它将使用相同的默认 dict,而该默认 dict 恰好是该实体的所有实体所使用的种类,在同一个进程中,没有显式设置 p

当您放置一个测试实体时,进入数据存储区的是当时它的p的 pickle “快照”——当你 get 它回来时,它将恢复到那个状态,现在与 default single-dict-per 的其他可能使用断开连接-过程。但这些只是这种可疑用法中的更多反常现象。

简而言之,可变默认值 在 Python 中不是一个好主意——人们几乎不会正确使用它们。这适用于对 ndb.PickleProperty 的调用,至少与对其他 Python 可调用对象的任何其他调用一样多!

添加:如果您需要一个 PickleProperty 来专门保存一个字典,并且发现每次实例化那种实体时显式添加 p={} 太麻烦, 子类化 PickleProperty 可能会有帮助。即:

class DictPickleProperty(ndb.PickleProperty):
def __init__(self, **kwds):
kwds['default'] = kwds.get('default', {})
super(DictPickleProperty, self).__init__(**kwds)

如果 default 是 (A) 未指定,或 (B) 指定为不是 dict 的内容,您想要做什么当然取决于您。这个简单的例子在情况 (B) 中没有做任何特别的事情——(所以例如 default=[] 仍然会导致问题)——但是确实使用了一个新的 empy dict 以防万一(A).

或者,您可以尝试将任何提供的 default 值转换为新的 dict(因此 []{} 会创建一个新的空 dict,但许多其他值会引发异常):

        kwds['default'] = dict(kwds.get('default', ()))

当然,还有许多其他变体。

关于python - 字典的 GAE NDB PickleProperty : new entity taking old property?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28387723/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com