#7495: Review of Programming FAQ by Florent Xicluna.
This commit is contained in:
parent
bfe95ac098
commit
62eaaf62ff
|
@ -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
|
||||||
``"".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.
|
||||||
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::
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
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::
|
||||||
|
|
||||||
a = B()
|
a = B()
|
||||||
b = a
|
b = a
|
||||||
print b
|
print(b)
|
||||||
<__main__.A instance at 016D07CC>
|
<__main__.A object at 0x16D07CC>
|
||||||
print a
|
print(a)
|
||||||
<__main__.A instance at 016D07CC>
|
<__main__.A object 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
|
||||||
|
@ -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::
|
||||||
|
|
||||||
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::
|
||||||
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?
|
||||||
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
|
||||||
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
|
||||||
|
|
||||||
|
@ -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 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
|
||||||
|
@ -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?
|
||||||
|
|
||||||
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::
|
||||||
|
|
||||||
>>> 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.
|
||||||
* 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::
|
||||||
... "\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
|
||||||
|
@ -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
|
See the :ref:`unicode-howto`.
|
||||||
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``
|
|
||||||
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:
|
||||||
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.
|
||||||
|
@ -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
|
||||||
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
|
||||||
|
@ -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.
|
||||||
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 an 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
|
||||||
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
|
||||||
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.
|
||||||
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, use the built-in :func:`super` function::
|
Use 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::
|
||||||
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
|
||||||
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::
|
||||||
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.
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
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.pyc'>
|
<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'
|
||||||
|
|
Loading…
Reference in New Issue