Reputation: 5771
I'm getting back to programming for Google App Engine and I've found, in old, unused code, instances in which I wrote constructors for models. It seems like a good idea, but there's no mention of it online and I can't test to see if it works. Here's a contrived example, with no error-checking, etc.:
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()
The **kwargs are passed on to the Model constructor in case the model is constructed with a specified parent
or key_name
, or in case other properties (like age
) are specified. This constructor differs from the default in that it requires that a name
and breed_list
be specified (although it can't ensure that they're strings), and it parses breed_list
in a way that the default constructor could not.
Is this a legitimate form of instantiation, or should I just use functions or static/class methods? And if it works, why aren't custom constructors used more often?
Upvotes: 4
Views: 1091
Reputation: 4492
In your example, why not use the default syntax instead of a custom constructor:
rufus = Dog( name='Rufus', breeds=['spaniel','terrier','labrador'] )
Your version makes it less clear semantically IMHO.
As for overriding Model constructors, Google recommends against it (see for example: http://groups.google.com/group/google-appengine/browse_thread/thread/9a651f6f58875bfe/111b975da1b4b4db?lnk=gst&q=python+constructors#111b975da1b4b4db) and that's why we don't see it in Google's code. I think it's unfortunate because constructor overriding can be useful in some cases, like creating a temporary property.
One problem I know of is with Expando, anything you define in the constructor gets auto-serialized in the protocol buffer. But for base Models I am not sure what are the risks, and I too would be happy to learn more.
Upvotes: 2
Reputation: 89897
There's usually no need to do something like that; the default constructor will assign name
, and when working with a list it almost always makes more sense to pass an actual list instead of a space-separated string (just imagine the fun if you passed "cocker spaniel" instead of just "spaniel" there, for one thing...).
That said, if you really need to do computation when instantiating a Model subclass instance, there's probably nothing inherently wrong with it. I think most people probably prefer to get the data into the right form and then create the entity, which is why you're not seeing a lot of examples like that.
Upvotes: 1