Differences between revisions 15 and 17 (spanning 2 versions)
Revision 15 as of 2007-08-06 01:47:15
Size: 4809
Comment: CategoryDocumentation
Revision 17 as of 2007-08-23 20:17:16
Size: 5678
Editor: 72
Comment: added a note about absolute imports, taken from Collin Winter's blog post.
Deletions are marked like this. Additions are marked like this.
Line 4: Line 4:
in five five years from now... See
http://www.python.org/peps/pep-3000.html for more
five years from now. See
[http://www.python.org/peps/pep-3000.html PEP 3000] for more
Line 12: Line 12:
    '''Write unit tests for all new or refactored code'''     '''Write unit tests for all new or refactored code.'''
Line 17: Line 17:
two integers are divided, e.g. 3/2 => 1. While correct if we
assume that dividing integers means integer division (the
remainder is accessible through the modulo operator %)
it's
two integers are divided (e.g., {{{3/2}}} yields {{{1}}}). While this is correct if we
assume that dividing integers means integer division, it's
Line 21: Line 20:
a future Python version, so that a/b will yield a float as a
result even if both a and b are integers, and
a new floor division operator // will perform integer
division. See See http://www.python.org/peps/pep-0238.html
a future Python version, so that {{{a/b}}} will yield a float as a
result even if both {{{a}}} and {{{b}}} are integers, and
a new floor division operator {{{//}}} will perform integer
division. See See [http://www.python.org/peps/pep-0238.html PEP 238] for more information.
Line 26: Line 25:
    '''Use true and floor division in new code'''     '''Use true and floor division in new code.'''

You can enable the new behaviour in Python 2.x as follows:
Line 29: Line 30:
from __future__ import division # Enable the new behaviour

f =
3/2 # 1.5

i =
3//2 # 1
>>> from __future__ import division # Enable the new behaviour
>>> 3/2
1.5
>>> 3//2
1
Line 36: Line 37:
= Absolute imports =

In Python 2.x, imports are implicitly relative. For instance, if you're editing the file {{{foo/__init__.py}}} and want to import the module at {{{foo/bar.py}}}, you could use {{{import bar}}}.

In Python 3.0, this won't work, as all imports will be absolute by default. You should instead use {{{from foo import bar}}}; if you want to import a specific function or variable from {{{bar}}}, you can use relative imports, such as {{{from .bar import myfunction}}}). See [http://www.python.org/dev/peps/pep-0328/ PEP 328] for more information.

    '''Use absolute imports in new code.'''
Line 44: Line 52:
extra features. See http://www.python.org/doc/newstyle.html extra features. See [http://www.python.org/doc/newstyle.html New-style Classes] for more information.
Line 46: Line 54:
    '''Use new style classes in new code'''     '''Use new style classes in new code.'''
Line 65: Line 73:
Exception from Python 2.5. See http://www.python.org/peps/pep-0352.html Exception from Python 2.5. See [http://www.python.org/peps/pep-0352.html PEP 352] for more information.
Line 67: Line 75:
    '''When defining new exception classes, always inherit (directly or indirectly) from Exception'''     '''When defining new exception classes, always inherit (directly or indirectly) from {{{Exception}}}.'''
Line 77: Line 85:
    '''Write the {{{raise}}} statement with the exception object as the only argument'''     '''Write the {{{raise}}} statement with the exception object as the only argument.'''
Line 91: Line 99:
In the future, x < y and friends (>, <=, >=) will raise an exception instead of an arbitrary result, if type(x) != type(y) unless the types explicitly define the behaviour for these comparisions. In the future, {{{x < y}}} and friends ({{{>}}}, {{{<=}}}, {{{>=}}}) will raise an exception instead of an arbitrary result, if {{{type(x) != type(y)}}} unless the types explicitly define the behaviour for these comparisions.
Line 93: Line 101:
    '''Don't compare objects of different types with undefined comparison behaviour'''     '''Don't compare objects of different types with undefined comparison behaviour.'''
Line 97: Line 105:
One obvious way to test for inequality already exists: the '!=' operator. The rarely-used '<>' will go away. One obvious way to test for inequality already exists: the {{{!=}}} operator. The rarely-used {{{<>}}} will go away.
Line 99: Line 107:
    '''Use only {{{!=}}} for inequality comparison'''     '''Use only {{{!=}}} for inequality comparison.'''
Line 101: Line 109:
The syntax {{{`foo`}}} for repr() will not exist in Python 3.0. Almost all code currently uses {{{repr(foo)}}} for this purpose, and the backtick syntax is little-known and less readable. The backtick syntax {{{`foo`}}}, which is equivalent to {{{repr(foo)}}}, will not exist in Python 3.0. Almost all code currently uses {{{repr(foo)}}} for this purpose, and the backtick syntax is little-known and less readable.
Line 103: Line 111:
    '''Use only {{{repr(foo)}}} for the representation of an object'''     '''Use only {{{repr(foo)}}} for the representation of an object.'''
Line 109: Line 117:
    '''Don't assign to names that will become keywords'''     '''Don't assign to names that will become keywords.'''
Line 115: Line 123:
 * Collin Winter have some tips in: [http://oakwinter.com/code/porting-setuptools-to-py3k/]  * Collin Winter has some tips in: [http://oakwinter.com/code/porting-setuptools-to-py3k/]
Line 121: Line 129:
is getting gradually enabled. (This example is from Python 2.3.) are gradually becoming enabled. (This example is from Python 2.3.)

Python is a mature language, but it hasn't stopped evolving, and there are some issues to consider when coding Python, if you want your code to work with the latest version of Python five years from now. See [http://www.python.org/peps/pep-3000.html PEP 3000] for more information.

Unit Tests

Automated testing is generally better than debugging, and is your safety-net for any kind of refactoring, not only when migrating to a newer Python. Use PyUnit (unittest), DocTest or any alternative (see UnitTests) to help you.

  • Write unit tests for all new or refactored code.

True Division

Since the beginning, Python has yielded an integer result when two integers are divided (e.g., 3/2 yields 1). While this is correct if we assume that dividing integers means integer division, it's not always obvious to beginners. This behaviour will change in a future Python version, so that a/b will yield a float as a result even if both a and b are integers, and a new floor division operator // will perform integer division. See See [http://www.python.org/peps/pep-0238.html PEP 238] for more information.

  • Use true and floor division in new code.

You can enable the new behaviour in Python 2.x as follows:

>>> from __future__ import division # Enable the new behaviour
>>> 3/2
1.5
>>> 3//2
1

Absolute imports

In Python 2.x, imports are implicitly relative. For instance, if you're editing the file foo/__init__.py and want to import the module at foo/bar.py, you could use import bar.

In Python 3.0, this won't work, as all imports will be absolute by default. You should instead use from foo import bar; if you want to import a specific function or variable from bar, you can use relative imports, such as from .bar import myfunction). See [http://www.python.org/dev/peps/pep-0328/ PEP 328] for more information.

  • Use absolute imports in new code.

New style classes

Currently, there are two kinds of classes in Python. The 'classic' or old style classes, and the new style classes. Old style classes will go away in Python 3.0, and while most code will still work when the default switches from old style to new style, there are some differences in semantics, and the new style classes have some extra features. See [http://www.python.org/doc/newstyle.html New-style Classes] for more information.

  • Use new style classes in new code.

Don't write

class X:
    pass

Write

class X(object):
    pass

Exception class inheritance

Starting from Python 3.0, all exceptions must be derived from BaseException, which will be the base class for KeyboardInterrupt, SystemExit and Exception from Python 2.5. See [http://www.python.org/peps/pep-0352.html PEP 352] for more information.

  • When defining new exception classes, always inherit (directly or indirectly) from Exception.

class MyException(Exception): pass

Arguments for raise statement

The raise statement currently accepts different syntaxes. This will be consolidated so that only one argument is allowed for raise: the exception object, created like any other object. Other syntaxes will be deprecated.

  • Write the raise statement with the exception object as the only argument.

Don't write:

raise MyException "A nasty error"

Instead, write:

raise MyException("A nasty error")

Comparison of incompatible types

In the future, x < y and friends (>, <=, >=) will raise an exception instead of an arbitrary result, if type(x) != type(y) unless the types explicitly define the behaviour for these comparisions.

  • Don't compare objects of different types with undefined comparison behaviour.

Deprecation of little-used alternative operators

One obvious way to test for inequality already exists: the != operator. The rarely-used <> will go away.

  • Use only != for inequality comparison.

The backtick syntax `foo`, which is equivalent to repr(foo), will not exist in Python 3.0. Almost all code currently uses repr(foo) for this purpose, and the backtick syntax is little-known and less readable.

  • Use only repr(foo) for the representation of an object.

New keywords

All of the names with, as, nonlocal, True and False are becoming keywords. Code that attempts to assign to those names will generate an exception in Python 3.0.

  • Don't assign to names that will become keywords.

See more

Here are some more tips on writing Python code to be future proof with Python 3.0.

More changes in the future?

The following little code might be useful to run when you upgrade to a new Python version. It shows how some new features in Python are gradually becoming enabled. (This example is from Python 2.3.)

>>> import __future__
>>> for x in __future__.all_feature_names:
...     print x, eval('__future__.'+x)
... 
nested_scopes _Feature((2, 1, 0, 'beta', 1), (2, 2, 0, 'alpha', 0), 16)
generators _Feature((2, 2, 0, 'alpha', 1), (2, 3, 0, 'final', 0), 4096)
division _Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192)

The second tuple (e.g. (3, 0, 0, 'alpha', 0) for division) shows when a new feature will become the default.


CategoryDocumentation

FutureProofPython (last edited 2019-10-19 22:14:19 by FrancesHocutt)

Unable to edit the page? See the FrontPage for instructions.