On Sat, Feb 20, 2010 at 11:25 AM, egasimus <fallenbl...@gmail.com> wrote: > Hi, newbie here. I've read on using the 'global' keyword being > discouraged; then what is the preferred way to have something, for > example a class containing program settings, accessible from > everywhere, in a program spanning multiple files?
One of the powerful concepts to come out of Lisp was "dynamic scope". This is the ideal solution for configuration and logging. "Lexical scope" is where the value of the variables are found in the file it was defined in. This is what Python does, and it's what you're used to in most other languages. "Dynamic scope" is where the value of the variables are found by looking up the call stack. This is similar to perl's "local" keyword. It's also similar to environment variables, if you consider programs that run programs that run programs as similar to functions. (If you're familiar with neither, then that's fine.) This is useful for a program where you know it needs configuration or logging, but you don't want to have to specify it as part of the program. Whoever calls the program needs to configure it and setup their logger before calling it. Unfortunately, there is no built-in way to deal with dynamic variables in Python. But that doesn't mean you can't emulate it explicitly and clearly! In order to emulate it, you simply pass the configuration and such down to the functions you call. Each function or class instance needs to pass it further along. So, rather than: def foo(): bar() def bar() ... you need to have: def foo(config): bar(config) def bar(config): ... Obviously, only certain functions care for the config and logging setup. Others don't. And obviously, you can modify the value on the way down. Just be sure to make a copy or you'll change the entire stack's value for that configuration. There are a couple of systems that do something close to this. I don't know of any, except SQLAlchemy, that does this exactly right. WSGI is also a system that does this right, although I don't know that many people realize it. Usually, what people end up doing is setting the config values to some global in some module. Then everyone is expected to look in that module for the config. This ends up being messy, particularly for testing where you'd like to mess with the config without messing with THE config. You can tell it's messy because people end up writing code like this: old_value = get_config(...) set_config(... some new value ...) ... do your stuff ... set_config(...back to old_value...) This kind of code is hard to get right. (What happens if there is an exception before you set the old config back? That's right, you need a try-finally block.) In terms of "global", you should only really use "global" when you are need to assign to a lexically scoped variable that is shared among other functions. For instance: def foo(): i = 0 def inc(): global i; i+=1 def dec(): global i; i-=1 def get(): return i return (inc, dec, get) This really isn't that common, although it is useful. Note that the above might be better organized into a class instance. Good luck. -- Jonathan Gardner jgard...@jonathangardner.net -- http://mail.python.org/mailman/listinfo/python-list