Python's BNF

Paul McGuire ptmcg at austin.rr.com
Fri Feb 29 10:04:08 EST 2008


On Feb 29, 7:21 am, MartinRineh... at gmail.com wrote:
> So, as a nod to the anti-global school of thought, I changed 'ofile'
> to 'OFILE' so that it would at least look like a global constant.

Unfortunately, it's not constant at all.  Actually, what you have done
is worse.  Now you have taken a variable that has mutable state, that
changes in various places throughout the module, and made it look like
a nice safe dependable constant.


_OFILE = None
still_reading = False

def open_file(name):
    global _OFILE, still_reading
    _OFILE = open(name)
    still_reading = True

def process_line(function):
    function( _OFILE.readline() )

def extract_data(dataline):
    global _OFILE, still_reading
    if dataline.startswith("END"):
        close_file()

def close_file():
    global _OFILE, still_reading
    OFILE.close()
    OFILE = None
    still_reading = False

# main code
open_file()
while still_reading:
    process_line(extract_data)
close_file()


Of course, this is a semi-contrived example, but the scattered access
of OFILE and still_reading make sorting out this mess a, well, a
mess.  And I wouldn't really say that just passing around ofile as an
argument to every function is necessarily a sufficient solution.  I've
seen this approach run amok, with a global data structure
(representing the current runtime environment plus recent history,
plus database connection info, plus sundry other parts of the kitchen
sink) that was passed BY PROJECT CODING STANDARDS to EVERY FUNCTION IN
EVERY MODULE!  Supposedly, this was done to cure access problems to a
global data structure.  In fact, it solved none of the problems, AND
polluted every function signature to boot!

The main point is that access to ofile should be limited to those
functions that actually update it.  If ofile is a global, then there
is no control within a module over it, and if not named with a leading
'_', it is even visible externally to the module.  As Steve H said,
ideally this would be a hidden attribute within a class, accessed as
self._ofile, so that we would at least know that there is no access
beyond the boundaries of the class to this variable.  It would also
enhance the flexibility of the code - now by instantiating a second
instance of this class, I might be able to work with *two* files at
the same time, without any global array or list legerdemain.

-- Paul

class Horse:
    def lead_to_water(self):
        self.at_water = True
    def make_drink(self):
        raise AttributeException("can't do this")



More information about the Python-list mailing list