On Thu, 2003-05-22 at 16:10, Bud P.Bruegger wrote:
> I'm wondering what pickle does--it's kind of the same problem. Does
> it call __init__ during unpickling or just __new__??? While I haven't
> looked into the details, I'm quite positive the latter holds..
I don't know what exactly it does, but it doesn't call either __init__
or __new__ -- I believe it calls __setstate__, if you want to change how
pickle works on your object.
> For what it's worth, some free flowing thoughts on the issue of
> Person(12). It seems that our discussion so far has furthered each
> others understanding (open source at work), so here some more
> provocative thoughts:
>
> A python class has only a single "constructor", ie. a combination of
> __new__ and __init__. If you want multiple constructors, you have to
> subclass. I do this regularly to provide different __init__ with a
> signature specialized for different purposes. (And the rest of the
> subclass is unchanged).
>
> Applying this thought to Person(12), you really need an __init__ with
> a different signature (12, instead of name=..., age=...), so a
> subclass may be one solution. Is there a good naming convention for
> this? Maybe GetPerson(12) where GetPerson is a subclass of Person?
>
> But then, why does the act of retrieving an existing person from some
> storage (or namespace, to think more generally) need to be a class
> constructor? Why not Person.retrieve(12) or SQLObject.person(12) (both
> class methods)? Or actually Persons.get(12) may be a good way of
> putting it. (At least if the natural language of programming in
> English and application programmers don't chose to end their class
> names with and 's').
>
> If you went that latter way, you could have Person('Ian', 'Bicking',
> 'autor of SQLObject') as a constructor instead of a classmethod
> Person.new('Ian', 'Bicking', '...'). The former way seems to be what
> I expect from plain Python. Is there any specific rational why you
> reversed this?
Well, I don't have the entire reason formulated, but I'll give it a go.
__new__/_init is called on every *Python* object creation. It'd be a
pain to avoid that, and I don't think it *should* be avoided.
The reality is that there is a disconnect between database objects and
Python objects. SQLObject doesn't provide an object store, ala ZODB.
It maps, but there's no expectation that it will be perfect -- so
creating a Python object from the database row *is* a
creation/construction operation, it's not just like we've just brung the
object into memory from a different storage mechanism (as with pickle or
ZODB).
>From a purely pragmatic point of view, fetching is much more common than
constructing, so it's nice that it's shorter too.
> > Oh, and I'm not sure what we're talking about as far as properties go. When I
> > said 'manually defining properties will be ignored' i meant SQLObject doesn't
> > care about them, and they'll work fine.
>
> Not sure whether I misunderstand, so to find out here is how I think
> about the issue. Every column corrsponds to a property whose setter
> method is overloaded to store the object in the dbms. If application
> programmers have a reason to (independently of SQLObject) make the
> same attribute into a property, they have to possibly call SQLObject's
> setter method from their setter method (in the same way as the
> __init__ of a subclass usually calls the __init__ of the superclass).
> One possible example of such as thing would be to log all state
> changes to a file.
>
> So if this understanding of what is happening is accurate, application
> programmer need to take special steps when defining properties related
> to columns. Or to avoid that, use the non-standard-python shortcut
> method to define properties. So in any case, the way to define
> properties (related to columns) is different from that of plain pyton.
> In contrast, if column values are simply represented in the __dict__
> of the instance, everything is as in plain python.
Personally I find properties a little funny to work with anyway.
Hmmm... I guess using super() you can access properties in a superclass,
but the old techniques don't apply. But anyway, if you want to add
something to a property's getter or setter, you'd normally do it by
subclassing, etc, but there isn't really a superclass available with the
way SQLObject works. If you *do* subclass a SQLObject instance, you
probably could do what you want.
Anyway, the current situation just means you have to understand the way
some methods work, like _SO_get_columnName, or
_SO_getValue/_SO_setValue.
> > Agree with your summary that some form of transaction handling is required,
> > and hence delayed updates, if you want to sanely handle attribute
> > constraints/collisions.
>
> Yes, you're right with the constraints--haven't thought of these
> before. Moving from one consistent state of an object to another will
> often require the change of more than one attribute. Same idea as
> transactions...
>
> The other reason why I feel unconfortable about updating on every
> single attribute change is performance. Single attribute getter and
> setter methods are an antipattern of distributed computing...
>
> While SQLObject gives the possiblity to change several attributes at
> once (with the set method), in my view this is quite awkward: it kind
> of requires you to shadow the object with an object or an equivalent
> unstructured collection of local variables to prepare the new state.
> Usually, you would want to call several methods on the object in order
> to prepare a new consistent state. If you allow attribute assignments
> without committing, you can do that. The set method condemns you to
> do the same without using any class methods and thus gets in the way..
Using *Python* convention, if you want to ensure consistency you do so
*as each attribute is set*. People don't write Python objects that have
some uncommitted/committed state, where verification is delayed until
the commit.
If you need to check consistency among several attributes, you set them
all at once. I don't see a problem with that -- it's what I do for
non-database objects already.
Ian
|