[DB-SIG] format and pyformat redux
Chris Cogdon
chris@cogdon.org
Wed, 21 Aug 2002 19:11:43 -0700
I thought I'd just recap the previous discussion on format vs pyformat, s=
ince=20
I got a few responses privately. At the end, I'll also add a 'neat=20
suggestion' we can all champion or lampoon as appropriate.
I originally asked what where the advantages of pyformat over format. pyf=
ormat=20
seems to be the 'preferred' paramater passing mechanism, even though my o=
wn=20
experiences with 'pyformat' was that it was more cumbersome than 'format'=
=2E
However, when the number of parameters increases, it becomes more and mor=
e=20
difficult to maintain sequencing with the 'format' method, given that a=20
change in parameters necessitates a change in the order the parameters ar=
e=20
passed to the 'execute' method. For example, with the following compariso=
n,=20
it appears that 'format' is much simpler:
cur.execute ( "select * from people where name=3D%s and age>%s", name, ag=
e )
cur.execute ( "select * from people where name=3D%(name)s and age>%(age)s=
",
=09{'name':name,'age':age}
The shorter 'format' becomes more complex with, say, 10 or more parameter=
s.=20
(example omitted, I'm sure it's obvious to you all).
Additionally, you can do some neat tricks with the 'pyformat' method. If =
all=20
your variables are in your local namespace already, you can pass the outp=
ut=20
of 'vars'. Viz:
cur.execute ( "select * from people where name=3D%(name)s and age>%(age)s=
",=20
vars() )
In the cases where this is not the case, you can write a 'wrapper functio=
n' to=20
help you create the anonymous dictionary. Viz:
def execute2 ( cursor, format, **kwargs ):
return cursor.execute ( format, kwargs )
execute2 ( cur, "select * from people where name=3D%(name)s and age>%(age=
)s",=20
name=3Dgetname(), age=3Dgetage() )
So, thanks to you all fine folks out there, I dont find 'pyformat' as=20
unattractive anymore.
I do have an interesting proposition, though. (Stop groaning, you ;)
Currenty given the case where the information to be passed to the query i=
s not=20
currently in any local variable. To get it in there, either a local varia=
ble=20
needs to be created, and then the vars() function called to create the=20
dictionary, or a dictionary created to hold all the values. My suggestion=
for=20
another parameter passing format, and the opportunity to create a new gen=
eral=20
function for Python, is as follows:
We create a function that treats the information inside the () of the %=20
operator (or the execute statement) as a full python expression, rather t=
han=20
just a key into a dictionary. Since the current % expansion operator uses=
=20
parenthesis, it's perfectly reasonable to assume these are the surroundin=
g=20
parentesis of an expression, and evaluate the contents as a python=20
expression! Here's an example, assuming we have a new parameter passing=20
method called, say, pyexprformat (python expression format)
cur.execute ( "select * from people where name=3D%(name)s and age>%(age)s=
",=20
locals(), globals() )
Okay, so that's nothing new, but in this case, the stuff inside the=20
parenthesis is a python expression, and it's been told to evaluage in the=
=20
specified namespaces, just like 'eval'. Now, assume that the two paramete=
rs=20
need to be calculated, we could have:
cur.execute ( "select * from people where name=3D%(getname())s and=20
age>%(age())s", locals(), globals() )
I've shown an example of using a simple function call, but this could hav=
e=20
been any python expression.
To me, this seems to be very easy to set up. The syntax is clear, and I'm=
sure=20
there's a hook into the interpretor that would stop parsing tokens when t=
he=20
valid end of expression is reached (same syntax as function calls), we ge=
t=20
the value of the expression, do type checking to find out what kind of=20
quoting is necessary for SQL, and then we can continue parsing the string=
as=20
SQL :)
Apart from needing to specify the namespace, (and I'm sure we can get=20
reasonable defaults by playing with the python call stack) one does ot ne=
ed=20
to assign 'temporary' dictionary keys to get the information into the que=
ry=20
at all.
And finally, this can be expanded into a general python function for doin=
g=20
'expression-based' formatting strings, like the following:
formatexpr ( "Hello %(form['name'])s, if you are %(form['age'])s this yea=
r,=20
you'll be %(form['age']+1)s next year." )
Is this not nifty?
--=20
("`-/")_.-'"``-._ Chris Cogdon <chris@cogdon.org>
. . `; -._ )-;-,_`)
(v_,)' _ )`-.\ ``-'
_.- _..-_/ / ((.'
((,.-' ((,/ fL