谷歌应用引擎、Python和按值传递的对象
这其实是一个关于Python语言的问题,但它涉及到一个特定于Google App Engine的问题。
我们有
class User( db.Model ) : email = db.StringProperty() name = db.StringProperty() password = db.StringProperty() # more fields..
因为用户账户被频繁访问,我们使用gaeutilities在会话中保留了一份副本(作为额外的问题,这样在GAE上是否不好? 我想这样可以减轻数据库的负担。)
class UpdateProfile( webapp.RequestHandler ): def post( self ): # User posting update to his name self.session = sessions.Session() ####### # way#1: update the copy of the User object in SESSION, then .put() it self.session[ 'current_user' ].name = self.request.get( 'name' ) self.session[ 'current_user' ].put() # does not work. ####### ####### # way#2: make a copy of the User object in SESSION, then .put() it user = self.session[ 'current_user' ] user.name = self.request.get( 'name' ) user.put() # works to update the datastore, but the copy of user in self.session # is NOT UPDATED! I thought Python was # pass-by-reference. It is when you work with lists anyway. # Why isn't it "acting right" with this type of object?? ####### ####### # way#3: way that works. user = self.session[ 'current_user' ] user.name = self.request.get( 'name' ) user.put() self.session[ 'current_user' ] = user # works completely #######
这三种情况各自发生了什么?为什么情况1和2不工作?
3 个回答
2
我是gaeutilities的作者。我联系了Nick来讨论这个问题,他给了我一些很好的建议。在最终的1.3版本中,我会有一个解决方案。
3
我猜:
把对象放进会话(Session)里,意味着这些对象会被序列化(通常是用一种叫做“腌制”的方式),然后存储在某个地方(比如磁盘、内存或者数据库)。当你从会话中取出这些对象时,会根据之前保存的状态创建一个新的对象。
- 在第一个例子中,每次使用
self.session[ 'current_user' ]
都会得到一个新的对象,其中一个对象会被更新,另一个则会被保存到数据库。 - 在第二个例子中,你得到一个对象,把它保存到数据库,但不保存在会话里。
顺便提一下,Python 是“共享调用”的方式,但这和你的问题没有关系;-)
1
抱歉,我是这个网站的新手,不知道在哪里可以对答案进行评论?
不过,我已经解决了最初发帖时提到的具体问题。虽然数据的序列化(就是把数据转换成可以存储或传输的格式)还是不太理想,发生在写入的时候,但我确保在会话中将模型实体作为项目分配时能够正常工作。我没有选择重写序列化(这会是一个大工程),而是决定在将模型插入会话数据时进行检测,并为它设置一个引用属性。这意味着模型对象根本不需要经历序列化的过程。
如果与引用属性关联的实体被删除,当你尝试加载它时,会话中的引用属性也会被删除。这就意味着你需要处理一些异常,比如会话抛出的KeyError,就像处理字典一样。我希望这个解释足够直观,但我也欢迎任何评论。我会在接下来的几周内多次查看这个页面。