Kaydet (Commit) 0cedb4bf authored tarafından Georg Brandl's avatar Georg Brandl

#7495: backport Programming FAQ review to trunk.

üst 56989771
...@@ -176,31 +176,32 @@ Thus to get the same effect as:: ...@@ -176,31 +176,32 @@ Thus to get the same effect as::
it is much shorter and far faster to use :: it is much shorter and far faster to use ::
L2 = list(L1[:3]) # "list" is redundant if L1 is a list. L2 = list(L1[:3]) # "list" is redundant if L1 is a list.
Note that the functionally-oriented builtins such as :func:`map`, :func:`zip`, Note that the functionally-oriented builtins such as :func:`map`, :func:`zip`,
and friends can be a convenient accelerator for loops that perform a single and friends can be a convenient accelerator for loops that perform a single
task. For example to pair the elements of two lists together:: task. For example to pair the elements of two lists together::
>>> zip([1,2,3], [4,5,6]) >>> zip([1, 2, 3], [4, 5, 6])
[(1, 4), (2, 5), (3, 6)] [(1, 4), (2, 5), (3, 6)]
or to compute a number of sines:: or to compute a number of sines::
>>> map( math.sin, (1,2,3,4)) >>> map(math.sin, (1, 2, 3, 4))
[0.841470984808, 0.909297426826, 0.14112000806, -0.756802495308] [0.841470984808, 0.909297426826, 0.14112000806, -0.756802495308]
The operation completes very quickly in such cases. The operation completes very quickly in such cases.
Other examples include the ``join()`` and ``split()`` methods of string objects. Other examples include the ``join()`` and ``split()`` :ref:`methods
of string objects <string-methods>`.
For example if s1..s7 are large (10K+) strings then For example if s1..s7 are large (10K+) strings then
``"".join([s1,s2,s3,s4,s5,s6,s7])`` may be far faster than the more obvious ``"".join([s1,s2,s3,s4,s5,s6,s7])`` may be far faster than the more obvious
``s1+s2+s3+s4+s5+s6+s7``, since the "summation" will compute many ``s1+s2+s3+s4+s5+s6+s7``, since the "summation" will compute many
subexpressions, whereas ``join()`` does all the copying in one pass. For subexpressions, whereas ``join()`` does all the copying in one pass. For
manipulating strings, use the ``replace()`` method on string objects. Use manipulating strings, use the ``replace()`` and the ``format()`` :ref:`methods
regular expressions only when you're not dealing with constant string patterns. on string objects <string-methods>`. Use regular expressions only when you're
Consider using the string formatting operations ``string % tuple`` and ``string not dealing with constant string patterns. You may still use :ref:`the old %
% dictionary``. operations <string-formatting>` ``string % tuple`` and ``string % dictionary``.
Be sure to use the :meth:`list.sort` builtin method to do sorting, and see the Be sure to use the :meth:`list.sort` builtin method to do sorting, and see the
`sorting mini-HOWTO <http://wiki.python.org/moin/HowTo/Sorting>`_ for examples `sorting mini-HOWTO <http://wiki.python.org/moin/HowTo/Sorting>`_ for examples
...@@ -210,7 +211,7 @@ sorting in all but the most extreme circumstances. ...@@ -210,7 +211,7 @@ sorting in all but the most extreme circumstances.
Another common trick is to "push loops into functions or methods." For example Another common trick is to "push loops into functions or methods." For example
suppose you have a program that runs slowly and you use the profiler to suppose you have a program that runs slowly and you use the profiler to
determine that a Python function ``ff()`` is being called lots of times. If you determine that a Python function ``ff()`` is being called lots of times. If you
notice that ``ff ()``:: notice that ``ff()``::
def ff(x): def ff(x):
... # do something with x computing result... ... # do something with x computing result...
...@@ -331,24 +332,6 @@ actually modifying the value of the variable in the outer scope: ...@@ -331,24 +332,6 @@ actually modifying the value of the variable in the outer scope:
>>> print x >>> print x
11 11
In Python3, you can do a similar thing in a nested scope using the
:keyword:`nonlocal` keyword:
.. doctest::
:options: +SKIP
>>> def foo():
... x = 10
... def bar():
... nonlocal x
... print x
... x += 1
... bar()
... print x
>>> foo()
10
11
What are the rules for local and global variables in Python? What are the rules for local and global variables in Python?
------------------------------------------------------------ ------------------------------------------------------------
...@@ -411,7 +394,7 @@ using multiple imports per line uses less screen space. ...@@ -411,7 +394,7 @@ using multiple imports per line uses less screen space.
It's good practice if you import modules in the following order: It's good practice if you import modules in the following order:
1. standard library modules -- e.g. ``sys``, ``os``, ``getopt``, ``re``) 1. standard library modules -- e.g. ``sys``, ``os``, ``getopt``, ``re``
2. third-party library modules (anything installed in Python's site-packages 2. third-party library modules (anything installed in Python's site-packages
directory) -- e.g. mx.DateTime, ZODB, PIL.Image, etc. directory) -- e.g. mx.DateTime, ZODB, PIL.Image, etc.
3. locally-developed modules 3. locally-developed modules
...@@ -420,7 +403,7 @@ Never use relative package imports. If you're writing code that's in the ...@@ -420,7 +403,7 @@ Never use relative package imports. If you're writing code that's in the
``package.sub.m1`` module and want to import ``package.sub.m2``, do not just ``package.sub.m1`` module and want to import ``package.sub.m2``, do not just
write ``import m2``, even though it's legal. Write ``from package.sub import write ``import m2``, even though it's legal. Write ``from package.sub import
m2`` instead. Relative imports can lead to a module being initialized twice, m2`` instead. Relative imports can lead to a module being initialized twice,
leading to confusing bugs. leading to confusing bugs. See :pep:`328` for details.
It is sometimes necessary to move imports to a function or class to avoid It is sometimes necessary to move imports to a function or class to avoid
problems with circular imports. Gordon McMillan says: problems with circular imports. Gordon McMillan says:
...@@ -648,9 +631,9 @@ callable. Consider the following code:: ...@@ -648,9 +631,9 @@ callable. Consider the following code::
a = B() a = B()
b = a b = a
print b print b
<__main__.A instance at 016D07CC> <__main__.A instance at 0x16D07CC>
print a print a
<__main__.A instance at 016D07CC> <__main__.A instance at 0x16D07CC>
Arguably the class has a name: even though it is bound to two names and invoked Arguably the class has a name: even though it is bound to two names and invoked
through the name B the created instance is still reported as an instance of through the name B the created instance is still reported as an instance of
...@@ -680,7 +663,7 @@ What's up with the comma operator's precedence? ...@@ -680,7 +663,7 @@ What's up with the comma operator's precedence?
Comma is not an operator in Python. Consider this session:: Comma is not an operator in Python. Consider this session::
>>> "a" in "b", "a" >>> "a" in "b", "a"
(False, '1') (False, 'a')
Since the comma is not an operator, but a separator between expressions the Since the comma is not an operator, but a separator between expressions the
above is evaluated as if you had entered:: above is evaluated as if you had entered::
...@@ -689,7 +672,7 @@ above is evaluated as if you had entered:: ...@@ -689,7 +672,7 @@ above is evaluated as if you had entered::
not:: not::
>>> "a" in ("5", "a") >>> "a" in ("b", "a")
The same is true of the various assignment operators (``=``, ``+=`` etc). They The same is true of the various assignment operators (``=``, ``+=`` etc). They
are not truly operators but syntactic delimiters in assignment statements. are not truly operators but syntactic delimiters in assignment statements.
...@@ -731,12 +714,12 @@ solution is to implement the ``?:`` operator as a function:: ...@@ -731,12 +714,12 @@ solution is to implement the ``?:`` operator as a function::
if not isfunction(on_true): if not isfunction(on_true):
return on_true return on_true
else: else:
return apply(on_true) return on_true()
else: else:
if not isfunction(on_false): if not isfunction(on_false):
return on_false return on_false
else: else:
return apply(on_false) return on_false()
In most cases you'll pass b and c directly: ``q(a, b, c)``. To avoid evaluating In most cases you'll pass b and c directly: ``q(a, b, c)``. To avoid evaluating
b or c when they shouldn't be, encapsulate them within a lambda function, e.g.: b or c when they shouldn't be, encapsulate them within a lambda function, e.g.:
...@@ -766,7 +749,7 @@ Yes. Usually this is done by nesting :keyword:`lambda` within ...@@ -766,7 +749,7 @@ Yes. Usually this is done by nesting :keyword:`lambda` within
map(lambda x,y=y:y%x,range(2,int(pow(y,0.5)+1))),1),range(2,1000))) map(lambda x,y=y:y%x,range(2,int(pow(y,0.5)+1))),1),range(2,1000)))
# First 10 Fibonacci numbers # First 10 Fibonacci numbers
print map(lambda x,f=lambda x,f:(x<=1) or (f(x-1,f)+f(x-2,f)): f(x,f), print map(lambda x,f=lambda x,f:(f(x-1,f)+f(x-2,f)) if x>1 else 1: f(x,f),
range(10)) range(10))
# Mandelbrot set # Mandelbrot set
...@@ -792,10 +775,11 @@ Numbers and strings ...@@ -792,10 +775,11 @@ Numbers and strings
How do I specify hexadecimal and octal integers? How do I specify hexadecimal and octal integers?
------------------------------------------------ ------------------------------------------------
To specify an octal digit, precede the octal value with a zero. For example, to To specify an octal digit, precede the octal value with a zero, and then a lower
set the variable "a" to the octal value "10" (8 in decimal), type:: or uppercase "o". For example, to set the variable "a" to the octal value "10"
(8 in decimal), type::
>>> a = 010 >>> a = 0o10
>>> a >>> a
8 8
...@@ -811,17 +795,17 @@ or uppercase. For example, in the Python interpreter:: ...@@ -811,17 +795,17 @@ or uppercase. For example, in the Python interpreter::
178 178
Why does -22 / 10 return -3? Why does -22 // 10 return -3?
---------------------------- -----------------------------
It's primarily driven by the desire that ``i % j`` have the same sign as ``j``. It's primarily driven by the desire that ``i % j`` have the same sign as ``j``.
If you want that, and also want:: If you want that, and also want::
i == (i / j) * j + (i % j) i == (i // j) * j + (i % j)
then integer division has to return the floor. C also requires that identity to then integer division has to return the floor. C also requires that identity to
hold, and then compilers that truncate ``i / j`` need to make ``i % j`` have the hold, and then compilers that truncate ``i // j`` need to make ``i % j`` have
same sign as ``i``. the same sign as ``i``.
There are few real use cases for ``i % j`` when ``j`` is negative. When ``j`` There are few real use cases for ``i % j`` when ``j`` is negative. When ``j``
is positive, there are many, and in virtually all of them it's more useful for is positive, there are many, and in virtually all of them it's more useful for
...@@ -829,6 +813,12 @@ is positive, there are many, and in virtually all of them it's more useful for ...@@ -829,6 +813,12 @@ is positive, there are many, and in virtually all of them it's more useful for
ago? ``-190 % 12 == 2`` is useful; ``-190 % 12 == -10`` is a bug waiting to ago? ``-190 % 12 == 2`` is useful; ``-190 % 12 == -10`` is a bug waiting to
bite. bite.
.. note::
On Python 2, ``a / b`` returns the same as ``a // b`` if
``__future__.division`` is not in effect. This is also known as "classic"
division.
How do I convert a string to a number? How do I convert a string to a number?
-------------------------------------- --------------------------------------
...@@ -860,10 +850,11 @@ How do I convert a number to a string? ...@@ -860,10 +850,11 @@ How do I convert a number to a string?
To convert, e.g., the number 144 to the string '144', use the built-in type To convert, e.g., the number 144 to the string '144', use the built-in type
constructor :func:`str`. If you want a hexadecimal or octal representation, use constructor :func:`str`. If you want a hexadecimal or octal representation, use
the built-in functions ``hex()`` or ``oct()``. For fancy formatting, use the built-in functions :func:`hex` or :func:`oct`. For fancy formatting, see
:ref:`the % operator <string-formatting>` on strings, e.g. ``"%04d" % 144`` the :ref:`formatstrings` section, e.g. ``"{:04d}".format(144)`` yields
yields ``'0144'`` and ``"%.3f" % (1/3.0)`` yields ``'0.333'``. See the library ``'0144'`` and ``"{:.3f}".format(1/3)`` yields ``'0.333'``. You may also use
reference manual for details. :ref:`the % operator <string-formatting>` on strings. See the library reference
manual for details.
How do I modify a string in place? How do I modify a string in place?
...@@ -961,12 +952,12 @@ blank lines will be removed:: ...@@ -961,12 +952,12 @@ blank lines will be removed::
... "\r\n" ... "\r\n"
... "\r\n") ... "\r\n")
>>> lines.rstrip("\n\r") >>> lines.rstrip("\n\r")
"line 1 " 'line 1 '
Since this is typically only desired when reading text one line at a time, using Since this is typically only desired when reading text one line at a time, using
``S.rstrip()`` this way works well. ``S.rstrip()`` this way works well.
For older versions of Python, There are two partial substitutes: For older versions of Python, there are two partial substitutes:
- If you want to remove all trailing whitespace, use the ``rstrip()`` method of - If you want to remove all trailing whitespace, use the ``rstrip()`` method of
string objects. This removes all trailing whitespace, not just a single string objects. This removes all trailing whitespace, not just a single
...@@ -1092,26 +1083,26 @@ See the Python Cookbook for a long discussion of many ways to do this: ...@@ -1092,26 +1083,26 @@ See the Python Cookbook for a long discussion of many ways to do this:
If you don't mind reordering the list, sort it and then scan from the end of the If you don't mind reordering the list, sort it and then scan from the end of the
list, deleting duplicates as you go:: list, deleting duplicates as you go::
if List: if mylist:
List.sort() mylist.sort()
last = List[-1] last = mylist[-1]
for i in range(len(List)-2, -1, -1): for i in range(len(mylist)-2, -1, -1):
if last == List[i]: if last == mylist[i]:
del List[i] del mylist[i]
else: else:
last = List[i] last = mylist[i]
If all elements of the list may be used as dictionary keys (i.e. they are all If all elements of the list may be used as dictionary keys (i.e. they are all
hashable) this is often faster :: hashable) this is often faster ::
d = {} d = {}
for x in List: for x in mylist:
d[x] = x d[x] = 1
List = d.values() mylist = list(d.keys())
In Python 2.5 and later, the following is possible instead:: In Python 2.5 and later, the following is possible instead::
List = list(set(List)) mylist = list(set(mylist))
This converts the list into a set, thereby removing duplicates, and then back This converts the list into a set, thereby removing duplicates, and then back
into a list. into a list.
...@@ -1187,7 +1178,7 @@ How do I apply a method to a sequence of objects? ...@@ -1187,7 +1178,7 @@ How do I apply a method to a sequence of objects?
Use a list comprehension:: Use a list comprehension::
result = [obj.method() for obj in List] result = [obj.method() for obj in mylist]
More generically, you can try the following function:: More generically, you can try the following function::
...@@ -1212,23 +1203,17 @@ some changes and then compare it with some other printed dictionary. In this ...@@ -1212,23 +1203,17 @@ some changes and then compare it with some other printed dictionary. In this
case, use the ``pprint`` module to pretty-print the dictionary; the items will case, use the ``pprint`` module to pretty-print the dictionary; the items will
be presented in order sorted by the key. be presented in order sorted by the key.
A more complicated solution is to subclass ``UserDict.UserDict`` to create a A more complicated solution is to subclass ``dict`` to create a
``SortedDict`` class that prints itself in a predictable order. Here's one ``SortedDict`` class that prints itself in a predictable order. Here's one
simpleminded implementation of such a class:: simpleminded implementation of such a class::
import UserDict, string class SortedDict(dict):
class SortedDict(UserDict.UserDict):
def __repr__(self): def __repr__(self):
result = [] keys = sorted(self.keys())
append = result.append result = ("{!r}: {!r}".format(k, self[k]) for k in keys)
keys = self.data.keys() return "{{{}}}".format(", ".join(result))
keys.sort()
for k in keys:
append("%s: %s" % (`k`, `self.data[k]`))
return "{%s}" % string.join(result, ", ")
__str__ = __repr__ __str__ = __repr__
This will work for many common situations you might encounter, though it's far This will work for many common situations you might encounter, though it's far
from a perfect solution. The largest flaw is that if some values in the from a perfect solution. The largest flaw is that if some values in the
...@@ -1250,14 +1235,14 @@ The ``key`` argument is new in Python 2.4, for older versions this kind of ...@@ -1250,14 +1235,14 @@ The ``key`` argument is new in Python 2.4, for older versions this kind of
sorting is quite simple to do with list comprehensions. To sort a list of sorting is quite simple to do with list comprehensions. To sort a list of
strings by their uppercase values:: strings by their uppercase values::
tmp1 = [(x.upper(), x) for x in L] # Schwartzian transform tmp1 = [(x.upper(), x) for x in L] # Schwartzian transform
tmp1.sort() tmp1.sort()
Usorted = [x[1] for x in tmp1] Usorted = [x[1] for x in tmp1]
To sort by the integer value of a subfield extending from positions 10-15 in To sort by the integer value of a subfield extending from positions 10-15 in
each string:: each string::
tmp2 = [(int(s[10:15]), s) for s in L] # Schwartzian transform tmp2 = [(int(s[10:15]), s) for s in L] # Schwartzian transform
tmp2.sort() tmp2.sort()
Isorted = [x[1] for x in tmp2] Isorted = [x[1] for x in tmp2]
...@@ -1294,8 +1279,8 @@ out the element you want. :: ...@@ -1294,8 +1279,8 @@ out the element you want. ::
An alternative for the last step is:: An alternative for the last step is::
result = [] >>> result = []
for p in pairs: result.append(p[1]) >>> for p in pairs: result.append(p[1])
If you find this more legible, you might prefer to use this instead of the final If you find this more legible, you might prefer to use this instead of the final
list comprehension. However, it is almost twice as slow for long lists. Why? list comprehension. However, it is almost twice as slow for long lists. Why?
...@@ -1363,7 +1348,7 @@ particular behaviour, instead of checking the object's class and doing a ...@@ -1363,7 +1348,7 @@ particular behaviour, instead of checking the object's class and doing a
different thing based on what class it is. For example, if you have a function different thing based on what class it is. For example, if you have a function
that does something:: that does something::
def search (obj): def search(obj):
if isinstance(obj, Mailbox): if isinstance(obj, Mailbox):
# ... code to search a mailbox # ... code to search a mailbox
elif isinstance(obj, Document): elif isinstance(obj, Document):
...@@ -1466,8 +1451,8 @@ of resources) which base class to use. Example:: ...@@ -1466,8 +1451,8 @@ of resources) which base class to use. Example::
How do I create static class data and static class methods? How do I create static class data and static class methods?
----------------------------------------------------------- -----------------------------------------------------------
Static data (in the sense of C++ or Java) is easy; static methods (again in the Both static data and static methods (in the sense of C++ or Java) are supported
sense of C++ or Java) are not supported directly. in Python.
For static data, simply define a class attribute. To assign a new value to the For static data, simply define a class attribute. To assign a new value to the
attribute, you have to explicitly use the class name in the assignment:: attribute, you have to explicitly use the class name in the assignment::
...@@ -1486,9 +1471,9 @@ C)`` holds, unless overridden by ``c`` itself or by some class on the base-class ...@@ -1486,9 +1471,9 @@ C)`` holds, unless overridden by ``c`` itself or by some class on the base-class
search path from ``c.__class__`` back to ``C``. search path from ``c.__class__`` back to ``C``.
Caution: within a method of C, an assignment like ``self.count = 42`` creates a Caution: within a method of C, an assignment like ``self.count = 42`` creates a
new and unrelated instance vrbl named "count" in ``self``'s own dict. Rebinding new and unrelated instance named "count" in ``self``'s own dict. Rebinding of a
of a class-static data name must always specify the class whether inside a class-static data name must always specify the class whether inside a method or
method or not:: not::
C.count = 314 C.count = 314
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment