|
Cooking with Python
07/11/2002
|
by Robin Parma, Alex Martelli, Scott David Daniels, Ben Wolfson, Nick Perkins, Anurag Uniya, Tim Keating, Rael Dornfest and Jeremy Hylton, authors of the Python Cookbook
1. Simple Tests Using Exceptions
Usually Python is straightforward, but there are a few unexpected exceptions.
Credits: Robin Parma
Problem
You want to know if the contents of a string represent an integer, which is not quite the same thing as checking whether the string contains only digits.
Solution
# try/except is generally the best approach to such problems:
def IsInt(str):
"""Is the given string an integer?"""
try:int(str)
except ValueError:return 0
else:return 1
Discussion
Use exceptions to perform simple tests that are otherwise laborious. If you want to know if the contents of a string represent an integer, just try to convert it. That's what IsInt() does. The try/except mechanism catches the exception raised when the string cannot be converted to an int, turning it into a harmless return 0. The else clause, which runs only
when no exception is raised in the try clause, gives a return 1 when the string is OK.
Don't be misled by the word "exception," or by what is considered good style in different programming languages. Relying on exceptions and try/except is a useful Pythonic idiom.
2. Constants in Python
Liberal Python lets you rebind any variable; yet, there is an instance where you can protect your variables.
Credits: Alex Martelli
Problem
You need to define module-level variables that client-code cannot accidentally rebind, such as "named constants."
Solution
# Needs Python 2.1 or better. Put in const.py...:
class _Constants:
class ConstError(TypeError): pass
def __setattr__(self, name, value):
if self.__dict__.has_key(name):
raise self.ConstError, "Can't rebind const(%s)"%name
self.__dict__[name ] = value
def __delattr__(self, name):
if self.__dict__.has_key(name):
raise self.ConstError, "Can't unbind const(%s)"%name
raise NameError, name
import sys
sys.modules[__name__] = _Constants()
# now any client-code can:
import const
# and bind an attribute ONCE:
const.magic =23
# but NOT re-bind it:
# const.magic =88 # would raise const.ConstError
Discussion
In Python, any variable can be re-bound at will. Modules don't let you define special methods, such as an instance's __setattr__, to stop attribute re-binding. An easy solution (in Python 2.1 and up) is to use an instance as "module."
Python 2.1 and up no longer forces entries in sys.modules to be module objects. You can install an instance object there and take advantage of
its attribute-access special methods while still having client-code get at it with import somename. You might see this as a more Pythonic "Singleton"-ish idiom (but also see "Singleton? We don't need no stinkin' Singleton: the Borg non-pattern"). Note that this recipe ensures a constant binding for a given name, not an object's immutability, which is quite a different issue.
