Steven D'Aprano wrote: > When writing a script or application, name management is not a big deal. > But in a library, temporary variables are pollution. They make it harder > for the users of your library to tell what's part of the API and what > isn't, and they make "from module import *" less useful. So if I have a > temporary global variable, I may want to get rid of it once I'm finished > with it. Here's a snippet from a library module I have, designed to be > used with * imports: > > tmp = set(C0.keys()) & set(C1.keys()) > assert not tmp, 'duplicate control code acronyms: %s' % tmp > # Special check for SCG abbreviated acronym. > assert 'SGC' not in C0 > assert 'SGC' not in C1 > # Validate that the ^ and ESC codes are correct. > for C in (C0, C1): > for cc in C.values(): > assert cc.code == _code(cc.ordinal), 'failed check: %s' % cc > del C, cc, tmp > > Those three temporary variables, C, cc and tmp, would otherwise hang > around forever, polluting the namespace and confusing my module's users. > (My module's users, so far, is mostly me, but I'm easily confused.)
You are not alone with that design. The first thing that came up in the stdlib was the webbrowser module: $ cd /usr/lib/python3.4 $ find . -name \*.py -print0 | xargs -0 egrep '\bdel\s+(_|[[:alnum:]])+$' | head -n1 ./webbrowser.py: del cmdline $ Here's the relevant part of the code where the author manages to del two out of three helper variables: """ # OK, now that we know what the default preference orders for each # platform are, allow user to override them with the BROWSER variable. if "BROWSER" in os.environ: _userchoices = os.environ["BROWSER"].split(os.pathsep) _userchoices.reverse() # Treat choices in same way as if passed into get() but do register # and prepend to _tryorder for cmdline in _userchoices: if cmdline != '': cmd = _synthesize(cmdline, -1) if cmd[1] is None: register(cmdline, None, GenericBrowser(cmdline), -1) cmdline = None # to make del work if _userchoices was empty del cmdline del _userchoices """ I really don't like that approach; I prefer writing a helper function, properly marked as an implementation detail, e. g. def _setup_userchoices(userchoices=None): """ >>> _setup_userchoices(["one"]) >>> _tryorder[0] 'one' >>> _setup_userchoices(["two", "three"]) >>> _tryorder[:3] ['two', 'three', 'one'] """ if userchoices is None: userchoices = os.environ.get("BROWSER", "").split(os.pathsep) for cmdline in reversed(userchoices): if cmdline != "": cmd = _synthesize(cmdline, -1) if cmd[1] is None: register(cmdline, None, GenericBrowser(cmdline), -1) _setup_userchoices() That is easy to test (if this were for real you'd use unit test, not doctest), and you don't have to decide whether the leftover `cmd` is kept intentionally or by accident, or be careful to avoid that you tread on names that *are* part of the API. That are the advantages for the author/reader of the module. As a user the extra _setup_userchoices() function doesn't bother me at all. _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor