On 13/03/06, Kent Johnson <[EMAIL PROTECTED]> wrote: > Ed Singleton wrote: > > On 10/03/06, Kent Johnson <[EMAIL PROTECTED]> wrote: > > > >>Ed Singleton wrote: > >>>I want to use this in a few different places. For example Faces, the > >>>Python Project Management Planner Tool Thingy, uses nested functions > >>>to put tasks within a project: > >>> > >>>def MyProject(): > >>> start = "2006-03-06" > >>> resource = Me > >>> > >>> def Task1(): > >>> start = "2006-03-13" > >>> > >>> def Task2(): > >>> effort = "1w" > >>> > >>>I'd like to load these from a database (using SQLObject), but I'm not > >>>sure how I can define the name of the function from a filed in a > >>>database (or read in from a text file). > >> > >>This is truly bizarre use of nested functions. Faces must be looking at > >>the compiled function objects to pick this out. > > > > > > To be honest, this didn't seem that bizarre to me. If I understand > > properly (which I probably don't) functions are just callable objects > > like any other callable object (or at least can be treated as such). > > Isn't this just a handy way of creating a nested object structure > > that's readable? > > Why not just use nested dicts? > > MyProject = dict( > start = "2006-03-06", > resource = Me, > Task1 = dict(start = "2006-03-13"), > Task2 = dict(effort = "1w"), > ) > > Maybe the appearance isn't quite as nice but the intent is clear, the > code to access the data is *much* simpler, and it lends itself to the > kind of programmatic creation you are trying to do. Take a look at > task.Task._compile() in the faces source to see the gyrations it takes > to extract the data in functional form. The Zen of Python says, > "Explicit is better than implicit" > "Simple is better than complex"
Point taken. Dict's are easier. And the appearance is fine. I've just discovered with a little playing, that you can do: >>> def z(v): ... def f(x): ... print x * v ... return f ... >>> c = z(3) >>> c(1) 3 >>> funcdict = dict(foo = z(4)) >>> funcdict["foo"](1) 4 Which was obvious enough that I thought of trying it, but surprising enough that I was really pleased when it worked. > >>In general you can set an attribute of an object using setattr(): > >> setattr(foo, 'bar', 3) > >>is the same as > >> foo.bar = 3 > >>but the attribute name is specified as a string so it can be determined > >>at runtime. > > > > > > This makes sense, and I think I can see how I would use it. > > > > To create a bunch of objects from some data (just name and start date): > > > > for fname, startdate in data: > > def foo: > > start = "" > > setattr(foo, __name__, fname) > > setattr(foo, start, startdate) > > > > Sorting out the nesting should be fairly straightforward (if the above > > works). > > No, it won't work. A function attribute is not the same as a local > variable of the function. What you propose is essentially > def foo(): pass > foo.bar = 'data' > > but what you need is > def foo(): > bar = 'data' > > which is very different. > > faces looks at foo.func_code.co_names to find the names you have used, > and it actually runs the function with a tracing hook to capture the values. > > There doesn't seem to be any other way to define a Task in faces, > either. You have to actually create functions. I guess this might be a > good place to use exec - just create the source code for the function > defs in a string and exec it, then retrieve the function from the global > namespace and pass it to faces. Then tell me why this API is better than > using nested dicts. Agreed, though to be fair the author of faces has probably overcomplicated the code for handling it (which is a damn shame as it is really quite a nice project planning tool). I guess you can't blindly iterate over the methods of functions, as there are other methods there that you might not want to use (like setattr and stuff, maybe?). Ed _______________________________________________ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor