- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
对我来说看起来像是一个错误,但也许有人对此有一个合理的解释。考虑以下代码:
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/
我有一个 python 字典,我试图通过 pickle 属性存储在 GAE Gql 数据存储中。 我试着按照这个问题和答案, Store a list of dictionaries in GAE 但
对我来说看起来像是一个错误,但也许有人对此有一个合理的解释。考虑以下代码: class Test(ndb.Model): a= ndb.IntegerProperty() p = nd
我是一名优秀的程序员,十分优秀!