Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
62eaaf62
Commit
62eaaf62
authored
Dec 19, 2009
by
Georg Brandl
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
#7495: Review of Programming FAQ by Florent Xicluna.
parent
bfe95ac0
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
122 additions
and
165 deletions
+122
-165
Doc/faq/programming.rst
Doc/faq/programming.rst
+122
-165
No files found.
Doc/faq/programming.rst
View file @
62eaaf62
...
@@ -176,19 +176,19 @@ Thus to get the same effect as::
...
@@ -176,19 +176,19 @@ 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]
)
>>>
list(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
))
>>>
list(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.
...
@@ -197,10 +197,9 @@ For example if s1..s7 are large (10K+) strings then
...
@@ -197,10 +197,9 @@ 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()`` methods on
regular expressions only when you're not dealing with constant string patterns.
string objects. Use regular expressions only when you're not dealing with
Consider using the string formatting operations ``string % tuple`` and ``string
constant string patterns.
% 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 +209,7 @@ sorting in all but the most extreme circumstances.
...
@@ -210,7 +209,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...
...
@@ -387,7 +386,7 @@ main.py::
...
@@ -387,7 +386,7 @@ main.py::
import config
import config
import mod
import mod
print
config.x
print
(config.x)
Note that using a module is also the basis for implementing the Singleton design
Note that using a module is also the basis for implementing the Singleton design
pattern, for the same reason.
pattern, for the same reason.
...
@@ -408,16 +407,15 @@ using multiple imports per line uses less screen space.
...
@@ -408,16 +407,15 @@ 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
Never use relative package imports. If you're writing code that's in the
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 ``from . 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. See :pep:`328` for details.
leading to confusing bugs.
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:
...
@@ -499,7 +497,7 @@ desired effect in a number of ways.
...
@@ -499,7 +497,7 @@ desired effect in a number of ways.
x, y = 'old-value', 99
x, y = 'old-value', 99
x, y = func2(x, y)
x, y = func2(x, y)
print
x, y
# output: new-value 100
print
(x, y)
# output: new-value 100
This is almost always the clearest solution.
This is almost always the clearest solution.
...
@@ -513,7 +511,7 @@ desired effect in a number of ways.
...
@@ -513,7 +511,7 @@ desired effect in a number of ways.
args = ['old-value', 99]
args = ['old-value', 99]
func1(args)
func1(args)
print
args[0], args[1]
# output: new-value 100
print
(args[0], args[1])
# output: new-value 100
4) By passing in a dictionary that gets mutated::
4) By passing in a dictionary that gets mutated::
...
@@ -523,7 +521,7 @@ desired effect in a number of ways.
...
@@ -523,7 +521,7 @@ desired effect in a number of ways.
args = {'a':' old-value', 'b': 99}
args = {'a':' old-value', 'b': 99}
func3(args)
func3(args)
print
args['a'], args['b']
print
(args['a'], args['b'])
5) Or bundle up values in a class instance::
5) Or bundle up values in a class instance::
...
@@ -538,7 +536,7 @@ desired effect in a number of ways.
...
@@ -538,7 +536,7 @@ desired effect in a number of ways.
args = callByRef(a='old-value', b=99)
args = callByRef(a='old-value', b=99)
func4(args)
func4(args)
print
args.a, args.b
print
(args.a, args.b)
There's almost never a good reason to get this complicated.
There's almost never a good reason to get this complicated.
...
@@ -644,10 +642,10 @@ callable. Consider the following code::
...
@@ -644,10 +642,10 @@ callable. Consider the following code::
a = B()
a = B()
b = a
b = a
print
b
print
(b)
<__main__.A
instance at 0
16D07CC>
<__main__.A
object at 0x
16D07CC>
print
a
print
(a)
<__main__.A
instance at 0
16D07CC>
<__main__.A
object at 0x
16D07CC>
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
...
@@ -677,7 +675,7 @@ What's up with the comma operator's precedence?
...
@@ -677,7 +675,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::
...
@@ -686,7 +684,7 @@ above is evaluated as if you had entered::
...
@@ -686,7 +684,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.
...
@@ -728,12 +726,12 @@ solution is to implement the ``?:`` operator as a function::
...
@@ -728,12 +726,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.:
...
@@ -758,22 +756,24 @@ Is it possible to write obfuscated one-liners in Python?
...
@@ -758,22 +756,24 @@ Is it possible to write obfuscated one-liners in Python?
Yes. Usually this is done by nesting :keyword:`lambda` within
Yes. Usually this is done by nesting :keyword:`lambda` within
:keyword:`lambda`. See the following three examples, due to Ulf Bartelt::
:keyword:`lambda`. See the following three examples, due to Ulf Bartelt::
from functools import reduce
# Primes < 1000
# Primes < 1000
print
filter(None,map(lambda y:y*reduce(lambda x,y:x*y!=0,
print
(list(
filter(None,map(lambda y:y*reduce(lambda x,y:x*y!=0,
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
(list(map(lambda x,f=lambda x,f:(f(x-1,f)+f(x-2,f)) if x>1 else 1:
range(10
))
f(x,f), range(10))
))
# Mandelbrot set
# Mandelbrot set
print
(lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+y,map(lambda y,
print
(
(lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+y,map(lambda y,
Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,Sy=Sy,L=lambda yc,Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,i=IM,
Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,Sy=Sy,L=lambda yc,Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,i=IM,
Sx=Sx,Sy=Sy:reduce(lambda x,y:x+y,map(lambda x,xc=Ru,yc=yc,Ru=Ru,Ro=Ro,
Sx=Sx,Sy=Sy:reduce(lambda x,y:x+y,map(lambda x,xc=Ru,yc=yc,Ru=Ru,Ro=Ro,
i=i,Sx=Sx,F=lambda xc,yc,x,y,k,f=lambda xc,yc,x,y,k,f:(k<=0)or (x*x+y*y
i=i,Sx=Sx,F=lambda xc,yc,x,y,k,f=lambda xc,yc,x,y,k,f:(k<=0)or (x*x+y*y
>=4.0) or 1+f(xc,yc,x*x-y*y+xc,2.0*x*y+yc,k-1,f):f(xc,yc,x,y,k,f):chr(
>=4.0) or 1+f(xc,yc,x*x-y*y+xc,2.0*x*y+yc,k-1,f):f(xc,yc,x,y,k,f):chr(
64+F(Ru+x*(Ro-Ru)/Sx,yc,0,0,i)),range(Sx))):L(Iu+y*(Io-Iu)/Sy),range(Sy
64+F(Ru+x*(Ro-Ru)/Sx,yc,0,0,i)),range(Sx))):L(Iu+y*(Io-Iu)/Sy),range(Sy
))))(-2.1, 0.7, -1.2, 1.2, 30, 80, 24)
))))(-2.1, 0.7, -1.2, 1.2, 30, 80, 24)
)
# \___ ___/ \___ ___/ | | |__ lines on screen
# \___ ___/ \___ ___/ | | |__ lines on screen
# V V | |______ columns on screen
# V V | |______ columns on screen
# | | |__________ maximum of "iterations"
# | | |__________ maximum of "iterations"
...
@@ -789,10 +789,11 @@ Numbers and strings
...
@@ -789,10 +789,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 = 0
o
10
>>> a
>>> a
8
8
...
@@ -808,17 +809,17 @@ or uppercase. For example, in the Python interpreter::
...
@@ -808,17 +809,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 th
e
hold, and then compilers that truncate ``i /
/ j`` need to make ``i % j`` hav
e
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
...
@@ -848,8 +849,8 @@ unwanted side effects. For example, someone could pass
...
@@ -848,8 +849,8 @@ unwanted side effects. For example, someone could pass
directory.
directory.
:func:`eval` also has the effect of interpreting numbers as Python expressions,
:func:`eval` also has the effect of interpreting numbers as Python expressions,
so that e.g. ``eval('09')`` gives a syntax error because Python
regards numbers
so that e.g. ``eval('09')`` gives a syntax error because Python
does not allow
starting with '0' as octal (base 8
).
leading '0' in a decimal number (except '0'
).
How do I convert a number to a string?
How do I convert a number to a string?
...
@@ -857,10 +858,9 @@ How do I convert a number to a string?
...
@@ -857,10 +858,9 @@ 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:`string-formatting` section, e.g. ``"{:04d}".format(144)`` yields
yields ``'0144'`` and ``"%.3f" % (1/3.0)`` yields ``'0.333'``. See the library
``'0144'`` and ``"{:.3f}" % (1/3)`` yields ``'0.333'``.
reference manual for details.
How do I modify a string in place?
How do I modify a string in place?
...
@@ -871,19 +871,20 @@ ability, try converting the string to a list or use the array module::
...
@@ -871,19 +871,20 @@ ability, try converting the string to a list or use the array module::
>>> s = "Hello, world"
>>> s = "Hello, world"
>>> a = list(s)
>>> a = list(s)
>>> print
a
>>> print
(a)
['H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd']
['H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd']
>>> a[7:] = list("there!")
>>> a[7:] = list("there!")
>>> ''.join(a)
>>> ''.join(a)
'Hello, there!'
'Hello, there!'
>>> import array
>>> import array
>>> a = array.array('c', s)
>>> a = array.array('u', s)
>>> print a
>>> print(a)
array('c', 'Hello, world')
array('u', 'Hello, world')
>>> a[0] = 'y' ; print a
>>> a[0] = 'y'
array('c', 'yello world')
>>> print(a)
>>> a.tostring()
array('u', 'yello world')
>>> a.tounicode()
'yello, world'
'yello, world'
...
@@ -931,7 +932,7 @@ There are various techniques.
...
@@ -931,7 +932,7 @@ There are various techniques.
* Use :func:`locals` or :func:`eval` to resolve the function name::
* Use :func:`locals` or :func:`eval` to resolve the function name::
def myFunc():
def myFunc():
print
"hello"
print
("hello")
fname = "myFunc"
fname = "myFunc"
...
@@ -958,12 +959,12 @@ blank lines will be removed::
...
@@ -958,12 +959,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,
T
here are two partial substitutes:
For older versions of Python,
t
here 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
...
@@ -988,45 +989,10 @@ For more complicated input parsing, regular expressions more powerful than C's
...
@@ -988,45 +989,10 @@ For more complicated input parsing, regular expressions more powerful than C's
:cfunc:`sscanf` and better suited for the task.
:cfunc:`sscanf` and better suited for the task.
What does 'UnicodeError: ASCII [decoding,encoding] error: ordinal not in range(128)' mean?
What does 'UnicodeDecodeError' or 'UnicodeEncodeError' error mean?
------------------------------------------------------------------------------------------
-------------------------------------------------------------------
This error indicates that your Python installation can handle only 7-bit ASCII
strings. There are a couple ways to fix or work around the problem.
If your programs must handle data in arbitrary character set encodings, the
environment the application runs in will generally identify the encoding of the
data it is handing you. You need to convert the input to Unicode data using
that encoding. For example, a program that handles email or web input will
typically find character set encoding information in Content-Type headers. This
can then be used to properly convert input data to Unicode. Assuming the string
referred to by ``value`` is encoded as UTF-8::
value = unicode(value, "utf-8")
will return a Unicode object. If the data is not correctly encoded as UTF-8,
the above call will raise a :exc:`UnicodeError` exception.
If you only want strings converted to Unicode which have non-ASCII data, you can
try converting them first assuming an ASCII encoding, and then generate Unicode
objects if that fails::
try:
x = unicode(value, "ascii")
except UnicodeError:
value = unicode(value, "utf-8")
else:
# value was valid ASCII data
pass
It's possible to set a default encoding in a file called ``sitecustomize.py``
See the :ref:`unicode-howto`.
that's part of the Python library. However, this isn't recommended because
changing the Python-wide default encoding may cause third-party extension
modules to fail.
Note that on Windows, there is an encoding known as "mbcs", which uses an
encoding specific to your current locale. In many cases, and particularly when
working with COM, this may be an appropriate default encoding to use.
Sequences (Tuples/Lists)
Sequences (Tuples/Lists)
...
@@ -1089,26 +1055,26 @@ See the Python Cookbook for a long discussion of many ways to do this:
...
@@ -1089,26 +1055,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
L
ist:
if
myl
ist:
L
ist.sort()
myl
ist.sort()
last =
L
ist[-1]
last =
myl
ist[-1]
for i in range(len(
L
ist)-2, -1, -1):
for i in range(len(
myl
ist)-2, -1, -1):
if last ==
L
ist[i]:
if last ==
myl
ist[i]:
del
L
ist[i]
del
myl
ist[i]
else:
else:
last =
L
ist[i]
last =
myl
ist[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
L
ist:
for x in
myl
ist:
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(L
ist))
mylist = list(set(myl
ist))
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.
...
@@ -1184,15 +1150,7 @@ How do I apply a method to a sequence of objects?
...
@@ -1184,15 +1150,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::
def method_map(objects, method, arguments):
"""method_map([a,b], "meth", (1,2)) gives [a.meth(1,2), b.meth(1,2)]"""
nobjects = len(objects)
methods = map(getattr, objects, [method]*nobjects)
return map(apply, methods, [arguments]*nobjects)
Dictionaries
Dictionaries
...
@@ -1209,23 +1167,17 @@ some changes and then compare it with some other printed dictionary. In this
...
@@ -1209,23 +1167,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.UserD
ict`` to create a
A more complicated solution is to subclass ``
d
ict`` 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
...
@@ -1247,18 +1199,18 @@ The ``key`` argument is new in Python 2.4, for older versions this kind of
...
@@ -1247,18 +1199,18 @@ 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]
Note that
Isorted may also be computed by ::
For versions prior to 3.0,
Isorted may also be computed by ::
def intfield(s):
def intfield(s):
return int(s[10:15])
return int(s[10:15])
...
@@ -1276,23 +1228,24 @@ is slower than the Schwartzian Transform.
...
@@ -1276,23 +1228,24 @@ is slower than the Schwartzian Transform.
How can I sort one list by values from another list?
How can I sort one list by values from another list?
----------------------------------------------------
----------------------------------------------------
Merge them into a
single list
of tuples, sort the resulting list, and then pick
Merge them into a
n iterator
of tuples, sort the resulting list, and then pick
out the element you want. ::
out the element you want. ::
>>> list1 = ["what", "I'm", "sorting", "by"]
>>> list1 = ["what", "I'm", "sorting", "by"]
>>> list2 = ["something", "else", "to", "sort"]
>>> list2 = ["something", "else", "to", "sort"]
>>> pairs = zip(list1, list2)
>>> pairs = zip(list1, list2)
>>> pairs = sorted(pairs)
>>> pairs
>>> pairs
[('what', 'something'), ("I'm", 'else'), ('sorting', 'to'), ('by', 'sort')]
[("I'm", 'else'), ('by', 'sort'), ('sorting', 'to'), ('what', 'something')]
>>> pairs.sort()
>>> result = [x[1] for x in pairs]
>>> result = [ x[1] for x in pairs ]
>>> result
>>> result
['else', 'sort', 'to', 'something']
['else', 'sort', 'to', 'something']
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?
...
@@ -1351,7 +1304,7 @@ Use the built-in function ``isinstance(obj, cls)``. You can check if an object
...
@@ -1351,7 +1304,7 @@ Use the built-in function ``isinstance(obj, cls)``. You can check if an object
is an instance of any of a number of classes by providing a tuple instead of a
is an instance of any of a number of classes by providing a tuple instead of a
single class, e.g. ``isinstance(obj, (class1, class2, ...))``, and can also
single class, e.g. ``isinstance(obj, (class1, class2, ...))``, and can also
check whether an object is one of Python's built-in types, e.g.
check whether an object is one of Python's built-in types, e.g.
``isinstance(obj, str)`` or ``isinstance(obj, (int,
long,
float, complex))``.
``isinstance(obj, str)`` or ``isinstance(obj, (int, float, complex))``.
Note that most programs do not use :func:`isinstance` on user-defined classes
Note that most programs do not use :func:`isinstance` on user-defined classes
very often. If you are developing the classes yourself, a more proper
very often. If you are developing the classes yourself, a more proper
...
@@ -1360,7 +1313,7 @@ particular behaviour, instead of checking the object's class and doing a
...
@@ -1360,7 +1313,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):
...
@@ -1430,17 +1383,17 @@ local state for self without causing an infinite recursion.
...
@@ -1430,17 +1383,17 @@ local state for self without causing an infinite recursion.
How do I call a method defined in a base class from a derived class that overrides it?
How do I call a method defined in a base class from a derived class that overrides it?
--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
If you're using new-style classes, u
se the built-in :func:`super` function::
U
se the built-in :func:`super` function::
class Derived(Base):
class Derived(Base):
def meth (self):
def meth (self):
super(Derived, self).meth()
super(Derived, self).meth()
If you're using classic classes: For a class definition such as ``
class
For version prior to 3.0, you may be using classic classes: For a
class
Derived(Base): ...`` you can call method ``meth()`` defined in ``Base`` (or one
definition such as ``class Derived(Base): ...`` you can call method ``meth()``
of ``Base``'s base classes) as ``Base.meth(self, arguments...)``. Here
,
defined in ``Base`` (or one of ``Base``'s base classes) as ``Base.meth(self
,
``Base.meth`` is an unbound method, so you need to provide the ``self``
arguments...)``. Here, ``Base.meth`` is an unbound method, so you need to
argument.
provide the ``self``
argument.
How can I organize my code to make it easier to change the base class?
How can I organize my code to make it easier to change the base class?
...
@@ -1463,8 +1416,8 @@ of resources) which base class to use. Example::
...
@@ -1463,8 +1416,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::
...
@@ -1483,9 +1436,9 @@ C)`` holds, unless overridden by ``c`` itself or by some class on the base-class
...
@@ -1483,9 +1436,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
...
@@ -1536,9 +1489,9 @@ default arguments. For example::
...
@@ -1536,9 +1489,9 @@ default arguments. For example::
class C:
class C:
def __init__(self, i=None):
def __init__(self, i=None):
if i is None:
if i is None:
print
"No arguments"
print
("No arguments")
else:
else:
print
"Argument is", i
print
("Argument is", i)
This is not entirely equivalent, but close enough in practice.
This is not entirely equivalent, but close enough in practice.
...
@@ -1597,11 +1550,13 @@ which allows you to point to objects without incrementing their reference count.
...
@@ -1597,11 +1550,13 @@ which allows you to point to objects without incrementing their reference count.
Tree data structures, for instance, should use weak references for their parent
Tree data structures, for instance, should use weak references for their parent
and sibling references (if they need them!).
and sibling references (if they need them!).
If the object has ever been a local variable in a function that caught an
.. XXX relevant for Python 3?
expression in an except clause, chances are that a reference to the object still
exists in that function's stack frame as contained in the stack trace.
If the object has ever been a local variable in a function that caught an
Normally, calling :func:`sys.exc_clear` will take care of this by clearing the
expression in an except clause, chances are that a reference to the object
last recorded exception.
still exists in that function's stack frame as contained in the stack trace.
Normally, calling :func:`sys.exc_clear` will take care of this by clearing
the last recorded exception.
Finally, if your :meth:`__del__` method raises an exception, a warning message
Finally, if your :meth:`__del__` method raises an exception, a warning message
is printed to :data:`sys.stderr`.
is printed to :data:`sys.stderr`.
...
@@ -1669,7 +1624,7 @@ provide a command-line interface or a self-test, and only execute this code
...
@@ -1669,7 +1624,7 @@ provide a command-line interface or a self-test, and only execute this code
after checking ``__name__``::
after checking ``__name__``::
def main():
def main():
print
'Running test...'
print
('Running test...')
...
...
if __name__ == '__main__':
if __name__ == '__main__':
...
@@ -1758,8 +1713,9 @@ consisting of many modules where each one imports the same basic module, the
...
@@ -1758,8 +1713,9 @@ consisting of many modules where each one imports the same basic module, the
basic module would be parsed and re-parsed many times. To force rereading of a
basic module would be parsed and re-parsed many times. To force rereading of a
changed module, do this::
changed module, do this::
import imp
import modname
import modname
reload(modname)
imp.
reload(modname)
Warning: this technique is not 100% fool-proof. In particular, modules
Warning: this technique is not 100% fool-proof. In particular, modules
containing statements like ::
containing statements like ::
...
@@ -1771,17 +1727,18 @@ module contains class definitions, existing class instances will *not* be
...
@@ -1771,17 +1727,18 @@ module contains class definitions, existing class instances will *not* be
updated to use the new class definition. This can result in the following
updated to use the new class definition. This can result in the following
paradoxical behaviour:
paradoxical behaviour:
>>> import imp
>>> import cls
>>> import cls
>>> c = cls.C() # Create an instance of C
>>> c = cls.C() # Create an instance of C
>>> reload(cls)
>>>
imp.
reload(cls)
<module 'cls' from 'cls.py
c
'>
<module 'cls' from 'cls.py'>
>>> isinstance(c, cls.C) # isinstance is false?!?
>>> isinstance(c, cls.C) # isinstance is false?!?
False
False
The nature of the problem is made clear if you print out the class objects:
The nature of the problem is made clear if you print out the "identity" of the
class objects:
>>> c.__class__
<class cls.C at 0x7352a0>
>>> cls.C
<class cls.C at 0x4198d0>
>>> hex(id(c.__class__))
'0x7352a0'
>>> hex(id(cls.C))
'0x4198d0'
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment