Functional Python Programming

(Wang) #1
Chapter 3

We can't easily eliminate all stateful Python objects, except from small programs.
Therefore, we must manage state while still exploiting the strengths of functional
design. Toward this end, we should always use the with statement to encapsulate
stateful file objects into a well-defined scope.


Always use file objects in a with context.

We should always avoid global file objects, global database connections, and the
associated state issues. The global file object is a very common pattern for handling
open files. We might have a function as shown in the following command snippet:


def open(iname, oname):
global ifile, ofile
ifile= open(iname, "r")
ofile= open(oname, "w")


Given this context, numerous other functions can use the ifile and ofile variables,
hoping they properly refer to the global files, which are left open for the application
to use.


This is not a very good design, and we need to avoid it. The files should be proper
parameters to functions, and the open files should be nested in a with statement to
assure that their stateful behavior is handled properly.


This design pattern also applies to databases. A database connection object can
generally be provided as a formal argument to the application's functions. This
is contrary to the way some popular web frameworks work that rely on a global
database connection in an effort to make the database a transparent feature of the
application. Additionally, a multithreaded web server might not benefit from sharing
a single database connection. This suggests that there are some benefits of a hybrid
approach that uses functional design with a few isolated stateful features.


Functions as first-class objects


It shouldn't come as a surprise that Python functions are first-class objects. In Python,
functions are objects with a number of attributes. The reference manual lists a
number of special member names that apply to functions. Since functions are objects
with attributes, we can extract the docstring function or the name of a function,
using special attributes such as doc or name. We can also extract the body
of the function via the code attribute. In compiled languages, this introspection
is relatively complex because of the source information that needs to be retained. In
Python, it's quite simple.

Free download pdf