python-peps/pep-0290.txt

176 lines
6.5 KiB
Plaintext
Raw Normal View History

PEP: 290
Title: Code Migration and Modernization
Version: $Revision$
Last-Modified: $Date$
Author: python@rcn.com (Raymond D. Hettinger)
Status: Active
Type: Informational
Created: 6-Jun-2002
Post-History:
Abstract
This PEP is a collection of procedures and ideas for updating
Python applications when newer versions of Python are installed.
The migration tips highlight possible areas of incompatibility and
make suggestions on how to find and resolve those differences. The
modernization procedures show how older code can be updated to
take advantage of new language features.
Rationale
This repository of procedures serves as a catalog or checklist of
known migration issues and procedures for addressing those issues.
Migration issues can arise for several reasons. Some obsolete
features are slowly deprecated according to the guidelines in PEP 4.
Also, some code relies on undocumented behaviors which are subject to
change between versions. Some code may rely on behavior which was
subsequently shown to be a bug and that behavior changes when the bug
is fixed.
Modernization options arise when new versions of Python add features
that allow improved clarity or higher performance than previously
available.
Guidelines for New Entries
Developers with commit access may update the PEP directly. Others
can send their ideas to a developer for possible inclusion.
While a consistent format makes the repository easier to use, feel
free to add or subtract sections to improve clarity.
Grep patterns may be supplied as tool to help maintainers locate
code for possible updates. However, fully automated search/replace
style regular expressions are not recommended. Instead, each code
fragment should be evaluated individually.
The contra-indications section is the most important part of a new
entry. It lists known situations where the update SHOULD NOT be
applied.
Modernization Procedures
Pattern: if d.has_key(k): --> if k in d:
Idea: For testing dictionary membership, use the 'in' keyword
instead of the 'has_key()' method.
Version: 2.2 or greater
Benefits: The result is shorter and more readable. The style becomes
consistent with tests for membership in lists. The result is
slightly faster because has_key requires an attribute search
and uses a relatively expensive CALL FUNCTION op code.
Locating: grep has_key
Contra-indications:
1. if dictlike.has_key(k) ## objects like shelve do not define
__contains__()
Pattern: for k in d.keys() --> for k in d
for k in d.items() --> for k in d.iteritems()
for k in d.values() --> for k in d.itervalues()
Idea: Use the new iter methods for looping over dictionaries
Version: 2.2 or greater
Benefits: The iter methods are faster because the do not have to create
a new list object with a complete copy of all of the keys,
values, or items. Selecting only keys, items, or values as
needed saves the time for creating throwaway object references
and, in the case of items, saves a second hash look-up of
the key.
Contra-indications:
1. def getids(): return d.keys() ## do not change the return type
2. for k in dictlike.keys() ## objects like shelve do not define
itermethods
3. k = d.keys(); j = k[:] ## iterators do not support slicing,
sorting or other operations
4. for k in d.keys(): del[k] ## dict iterators prohibit modifying the
dictionary
Pattern: if v == None --> if v is None:
if v != None --> if v is not None:
Idea: Since there is only one None object, equality can be tested
with identity.
Version: All
Benefits: Identity tests are slightly faster than equality tests. Also,
some object types may overload comparison to be much slower.
Locating: grep '== None' or grep '!= None'
Pattern: os.stat("foo")[stat.ST_MTIME] --> os.stat("foo").st_mtime
os.stat("foo")[stat.ST_MTIME] --> os.path.getmtime("foo")
Idea: Replace stat contants or indices with new stat methods
Version: 2.2 or greater
Benefits: The methods are not order dependent and do not require an
import of the stat module
Locating: grep os.stat
Pattern: import whrandom --> import random
Idea: Replace deprecated module
Version: 2.1 or greater
Benefits: All random methods collected in one place
Locating: grep whrandom
Pattern: import types ; type(v, types.IntType) --> isinstance(v, int)
type(s, types.StringTypes --> isinstance(s, basestring)
Idea: The types module will likely to be deprecated in the future.
Version: 2.2 or greater
Benefits: May be slightly faster, avoid a deprecated feature.
Locating: grep types *.py | grep import
Pattern: import string ; string.method(s, ...) --> s.method(...)
c in string.whitespace --> c.isspace()
Idea: The string module will likely to be deprecated in the future.
Version: 2.0 or greater
Benefits: Slightly faster, avoid a deprecated feature.
Locating: grep string *.py | grep import
Pattern: NewError = 'NewError' --> class NewError(Exception): pass
Idea: String exceptions are deprecated, derive from the Exception
base class.
Version: Any
Benefits: Unlike the obsolete string exceptions, class exceptions all
derive from another exception or the Exception base class.
This allows meaningful groupings of exceptions. It also
allows an "except Exception" clause to catch all exceptions.
Locating: Use PyChecker
Pattern: "foobar"[:3] == "foo" -> "foobar".startswith("foo")
"foobar"[-3:] == "bar" -> "foobar".endswith("bar")
Version: 2.0 or greater
Benefits: Faster because no slice has to be created. Less risk of
miscounting.
References
[1] PEP 4, Deprecation of Standard Modules
http://www.python.org/peps/pep-0004.html
Copyright
This document has been placed in the public domain.
Local Variables:
mode: indented-text
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
End: