Google App Engine(Python)模型的自定义构造函数
我最近又开始学习Google App Engine的编程,发现了一些以前写的旧代码,其中有我为模型写的构造函数。这个想法看起来不错,但网上没有相关的信息,我也没法测试它是否有效。下面是一个简单的例子,没有错误检查等等:
class Dog(db.Model):
name = db.StringProperty(required=True)
breeds = db.StringListProperty()
age = db.IntegerProperty(default=0)
def __init__(self, name, breed_list, **kwargs):
db.Model.__init__(**kwargs)
self.name = name
self.breeds = breed_list.split()
rufus = Dog('Rufus', 'spaniel terrier labrador')
rufus.put()
这里的**kwargs是传递给模型构造函数的,目的是为了在创建模型时,如果指定了parent
或key_name
,或者其他属性(比如age
)时可以使用。这个构造函数和默认的不同,它要求必须指定name
和breed_list
(虽然它不能确保这些是字符串),而且它处理breed_list
的方式是默认构造函数无法做到的。
这种创建对象的方式算不算合理?我是不是应该用函数或者静态/类方法?如果这个方法有效,为什么自定义构造函数不被更常用呢?
2 个回答
其实一般情况下不需要这样做;默认的构造函数会给name
赋值。而且在处理列表的时候,直接传一个真正的列表通常更合理,而不是传一个用空格分开的字符串(想象一下,如果你传的是“cocker spaniel”而不是“spaniel”,那可就麻烦了……)。
不过,如果你真的需要在创建一个模型子类实例的时候进行一些计算,那这样做也没有什么本质上的问题。我觉得大多数人更喜欢先把数据整理好,然后再创建实体,这也是为什么你很少看到这样的例子。
在你的例子中,为什么不使用默认的语法,而要用自定义的构造函数呢?
rufus = Dog( name='Rufus', breeds=['spaniel','terrier','labrador'] )
我觉得你的版本在语义上不太清晰。
关于重写模型的构造函数,谷歌是不推荐的(比如可以参考这个链接:http://groups.google.com/group/google-appengine/browse_thread/thread/9a651f6f58875bfe/111b975da1b4b4db?lnk=gst&q=python+constructors#111b975da1b4b4db),所以在谷歌的代码中我们看不到这种做法。我觉得这有点可惜,因为在某些情况下,重写构造函数是有用的,比如创建一个临时属性。
我知道的一个问题是关于Expando的,任何你在构造函数中定义的内容都会自动序列化到协议缓冲区中。但对于基础模型,我不太确定有什么风险,我也很想了解更多。