dict的GAE NDB PickleProperty:新实体接受旧属性?

2024-09-27 00:17:56 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

现在执行以下操作:

^{pr2}$

到这里,一切都很好。但现在:

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

全新的t2实例已经从t1分配了p值?!!在

除了一个错误,还有什么解释吗? 注意,执行t1的put()操作不会改变行为。在


Tags: 实例代码testdefaultmodelput错误class
1条回答
网友
1楼 · 发布于 2024-09-27 00:17:56

在Python中,默认参数会计算一次,因此您使用的是一个单个dict(您的default={}是每个进程的一个dict,而不是每个实体一个dict!)所有类型为Test的实体,它们恰好在同一个进程中,并且没有显式地为其设置{}。在

如果您这样做t=Test(p={}),那么{}就可以了,它有自己的dict。如果你做了t=Test(),然后t.p = {},你也会没事的。但是如果您不以某种方式设置实体的特定p,那么它将使用相同的默认值dict,这恰好是同一进程中所有此类实体所使用的默认值p,它没有显式设置p。在

当您put一个Test实体时,进入数据存储的是它的p的一个pickle“快照”,当您get返回时,它将恢复到该状态,并且现在与default单个-dict-的其他可能用途断开连接。但这些都是可疑用法中更多的反常现象。在

简言之,可变的默认值在Python中不是一个好主意,人们几乎从来没有正确地使用过它们。对ndb.PickleProperty的调用与对其他Python可调用对象的调用一样多!在

添加:如果您需要一个PickleProperty来专门保存dict,并且发现每次实例化这种实体时显式地添加p={}太麻烦了,那么子类化PickleProperty可能会有所帮助。一、 电子邮件:

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

如果default没有被指定,或者(B)被指定为不是dict的东西,你想怎么做当然取决于你。这个简单的例子在case(B)中没有任何特殊之处(因此,例如default=[]仍然会导致问题),但是在case(a)中使用了一个新的empy dict。在

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

^{pr2}$

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

相关问题 更多 >

    热门问题