On Sat, 20 Feb 2010 11:25:46 -0800, egasimus 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?
Such a thing is no different from keeping many global settings. It's not the global KEYWORD that is discouraged, but the over-use of global variables itself. See, for example: http://c2.com/cgi/wiki?GlobalVariablesAreBad http://weblogs.asp.net/wallen/archive/2003/05/08/6750.aspx In a nutshell: shared variables introduce tight coupling between parts of your code that should be independent. Whether they are truly global, or passed around in a Settings object, makes little or no difference. In both cases, the risks and problems are identical. Let me give a fanciful example: suppose your refrigerator, oven and shower all shared a single global temperature setting instead of having three local temperature settings. This would be a recipe for disaster: every operation to any of the three would need to carefully save the current temperature setting, and there's the constant risk of scalding showers, ruined foods, and undercooked meals. Having three different global temperature settings helps a bit, but that just expands the number of variables that everything has access too. Why do the television and the garage door need access to any temperature setting, let alone all three? Python globals aren't as bad as in some other languages, because "global" means global to a single module, not global to the entire program, but if you create a Settings object and import it from module to module, you break the encapsulation, *and* you then have the problem of needing to make sure it is initialised properly. http://archive.eiffel.com/doc/manuals/technology/bmarticles/joop/globals.html Global constants also aren't as bad, because the coupling is weaker. Unfortunately Python doesn't have constants, except by convention, so there's always the risk that some badly-behaved function might decide to redefine (say) math.pi to 3.15. Unfortunately, you probably can't get rid of globals altogether, but the tricks are (1) use as few of them as possible, and (2) make them local as quickly as possible. For example, you might have something like this: default_header = "My special header" # A global for option, argument in command_line: if option == "--header": default_header = argument class Printer: def print_page(self, text, header=None): if header is None: header = default_header print header print text I would limit the scope of default_header so that it was local to the printer class: for option, argument in command_line: if option == "--header": Printer.default_header = argument class Printer: default_header = "My special header" def print_page(self, text, header=None): if header is None: header = self.default_header print header print text You might not be able to completely eliminate either globals, or a Settings object, but you should be able to make it much, much smaller. In practice, to make testing easier, I'd split the command line processing into two steps: a function that reads and processes the command line into a single local settings object, then a separate function that applies those settings to the various classes. The function that reads the command line doesn't need to know where the settings eventually end up, and the function that applies the settings doesn't need to know where they come from. All the coupling between settings and classes is in one place, the second function, instead of scattered all over your code. -- Steven -- http://mail.python.org/mailman/listinfo/python-list