annotate Doc/faq/programming.rst @ 57303:4aa4c19dfaed legacy-trunk

#1757126: fix typo with the cyrillic_asian alias
author Philip Jenvey <pjenvey@underboss.org>
date Tue, 17 Nov 2009 02:42:26 +0000
parents 867d2f2735b8
children 896bf49628ab
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
56890
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1 :tocdepth: 2
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
2
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
3 ===============
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
4 Programming FAQ
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
5 ===============
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
6
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
7 .. contents::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
8
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
9 General Questions
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
10 =================
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
11
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
12 Is there a source code level debugger with breakpoints, single-stepping, etc.?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
13 ------------------------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
14
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
15 Yes.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
16
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
17 The pdb module is a simple but adequate console-mode debugger for Python. It is
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
18 part of the standard Python library, and is :mod:`documented in the Library
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
19 Reference Manual <pdb>`. You can also write your own debugger by using the code
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
20 for pdb as an example.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
21
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
22 The IDLE interactive development environment, which is part of the standard
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
23 Python distribution (normally available as Tools/scripts/idle), includes a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
24 graphical debugger. There is documentation for the IDLE debugger at
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
25 http://www.python.org/idle/doc/idle2.html#Debugger.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
26
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
27 PythonWin is a Python IDE that includes a GUI debugger based on pdb. The
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
28 Pythonwin debugger colors breakpoints and has quite a few cool features such as
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
29 debugging non-Pythonwin programs. Pythonwin is available as part of the `Python
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
30 for Windows Extensions <http://sourceforge.net/projects/pywin32/>`__ project and
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
31 as a part of the ActivePython distribution (see
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
32 http://www.activestate.com/Products/ActivePython/index.html).
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
33
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
34 `Boa Constructor <http://boa-constructor.sourceforge.net/>`_ is an IDE and GUI
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
35 builder that uses wxWidgets. It offers visual frame creation and manipulation,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
36 an object inspector, many views on the source like object browsers, inheritance
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
37 hierarchies, doc string generated html documentation, an advanced debugger,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
38 integrated help, and Zope support.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
39
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
40 `Eric <http://www.die-offenbachs.de/eric/index.html>`_ is an IDE built on PyQt
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
41 and the Scintilla editing component.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
42
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
43 Pydb is a version of the standard Python debugger pdb, modified for use with DDD
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
44 (Data Display Debugger), a popular graphical debugger front end. Pydb can be
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
45 found at http://bashdb.sourceforge.net/pydb/ and DDD can be found at
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
46 http://www.gnu.org/software/ddd.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
47
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
48 There are a number of commercial Python IDEs that include graphical debuggers.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
49 They include:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
50
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
51 * Wing IDE (http://wingware.com/)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
52 * Komodo IDE (http://www.activestate.com/Products/Komodo)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
53
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
54
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
55 Is there a tool to help find bugs or perform static analysis?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
56 -------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
57
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
58 Yes.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
59
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
60 PyChecker is a static analysis tool that finds bugs in Python source code and
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
61 warns about code complexity and style. You can get PyChecker from
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
62 http://pychecker.sf.net.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
63
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
64 `Pylint <http://www.logilab.org/projects/pylint>`_ is another tool that checks
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
65 if a module satisfies a coding standard, and also makes it possible to write
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
66 plug-ins to add a custom feature. In addition to the bug checking that
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
67 PyChecker performs, Pylint offers some additional features such as checking line
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
68 length, whether variable names are well-formed according to your coding
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
69 standard, whether declared interfaces are fully implemented, and more.
56492
9f765118d9b9 Fix broken links found by "make linkcheck". scipy.org seems to be done right now, so I could not verify links going there.
Georg Brandl <georg@python.org>
parents: 56890
diff changeset
70 http://www.logilab.org/card/pylint_manual provides a full list of Pylint's
9f765118d9b9 Fix broken links found by "make linkcheck". scipy.org seems to be done right now, so I could not verify links going there.
Georg Brandl <georg@python.org>
parents: 56890
diff changeset
71 features.
56890
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
72
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
73
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
74 How can I create a stand-alone binary from a Python script?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
75 -----------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
76
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
77 You don't need the ability to compile Python to C code if all you want is a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
78 stand-alone program that users can download and run without having to install
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
79 the Python distribution first. There are a number of tools that determine the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
80 set of modules required by a program and bind these modules together with a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
81 Python binary to produce a single executable.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
82
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
83 One is to use the freeze tool, which is included in the Python source tree as
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
84 ``Tools/freeze``. It converts Python byte code to C arrays; a C compiler you can
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
85 embed all your modules into a new program, which is then linked with the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
86 standard Python modules.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
87
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
88 It works by scanning your source recursively for import statements (in both
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
89 forms) and looking for the modules in the standard Python path as well as in the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
90 source directory (for built-in modules). It then turns the bytecode for modules
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
91 written in Python into C code (array initializers that can be turned into code
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
92 objects using the marshal module) and creates a custom-made config file that
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
93 only contains those built-in modules which are actually used in the program. It
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
94 then compiles the generated C code and links it with the rest of the Python
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
95 interpreter to form a self-contained binary which acts exactly like your script.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
96
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
97 Obviously, freeze requires a C compiler. There are several other utilities
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
98 which don't. One is Thomas Heller's py2exe (Windows only) at
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
99
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
100 http://www.py2exe.org/
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
101
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
102 Another is Christian Tismer's `SQFREEZE <http://starship.python.net/crew/pirx>`_
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
103 which appends the byte code to a specially-prepared Python interpreter that can
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
104 find the byte code in the executable.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
105
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
106 Other tools include Fredrik Lundh's `Squeeze
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
107 <http://www.pythonware.com/products/python/squeeze>`_ and Anthony Tuininga's
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
108 `cx_Freeze <http://starship.python.net/crew/atuining/cx_Freeze/index.html>`_.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
109
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
110
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
111 Are there coding standards or a style guide for Python programs?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
112 ----------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
113
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
114 Yes. The coding style required for standard library modules is documented as
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
115 :pep:`8`.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
116
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
117
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
118 My program is too slow. How do I speed it up?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
119 ---------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
120
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
121 That's a tough one, in general. There are many tricks to speed up Python code;
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
122 consider rewriting parts in C as a last resort.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
123
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
124 In some cases it's possible to automatically translate Python to C or x86
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
125 assembly language, meaning that you don't have to modify your code to gain
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
126 increased speed.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
127
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
128 .. XXX seems to have overlap with other questions!
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
129
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
130 `Pyrex <http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/>`_ can compile a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
131 slightly modified version of Python code into a C extension, and can be used on
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
132 many different platforms.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
133
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
134 `Psyco <http://psyco.sourceforge.net>`_ is a just-in-time compiler that
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
135 translates Python code into x86 assembly language. If you can use it, Psyco can
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
136 provide dramatic speedups for critical functions.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
137
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
138 The rest of this answer will discuss various tricks for squeezing a bit more
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
139 speed out of Python code. *Never* apply any optimization tricks unless you know
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
140 you need them, after profiling has indicated that a particular function is the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
141 heavily executed hot spot in the code. Optimizations almost always make the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
142 code less clear, and you shouldn't pay the costs of reduced clarity (increased
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
143 development time, greater likelihood of bugs) unless the resulting performance
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
144 benefit is worth it.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
145
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
146 There is a page on the wiki devoted to `performance tips
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
147 <http://wiki.python.org/moin/PythonSpeed/PerformanceTips>`_.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
148
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
149 Guido van Rossum has written up an anecdote related to optimization at
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
150 http://www.python.org/doc/essays/list2str.html.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
151
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
152 One thing to notice is that function and (especially) method calls are rather
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
153 expensive; if you have designed a purely OO interface with lots of tiny
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
154 functions that don't do much more than get or set an instance variable or call
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
155 another method, you might consider using a more direct way such as directly
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
156 accessing instance variables. Also see the standard module :mod:`profile` which
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
157 makes it possible to find out where your program is spending most of its time
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
158 (if you have some patience -- the profiling itself can slow your program down by
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
159 an order of magnitude).
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
160
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
161 Remember that many standard optimization heuristics you may know from other
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
162 programming experience may well apply to Python. For example it may be faster
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
163 to send output to output devices using larger writes rather than smaller ones in
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
164 order to reduce the overhead of kernel system calls. Thus CGI scripts that
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
165 write all output in "one shot" may be faster than those that write lots of small
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
166 pieces of output.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
167
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
168 Also, be sure to use Python's core features where appropriate. For example,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
169 slicing allows programs to chop up lists and other sequence objects in a single
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
170 tick of the interpreter's mainloop using highly optimized C implementations.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
171 Thus to get the same effect as::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
172
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
173 L2 = []
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
174 for i in range[3]:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
175 L2.append(L1[i])
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
176
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
177 it is much shorter and far faster to use ::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
178
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
179 L2 = list(L1[:3]) # "list" is redundant if L1 is a list.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
180
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
181 Note that the functionally-oriented builtins such as :func:`map`, :func:`zip`,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
182 and friends can be a convenient accelerator for loops that perform a single
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
183 task. For example to pair the elements of two lists together::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
184
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
185 >>> zip([1,2,3], [4,5,6])
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
186 [(1, 4), (2, 5), (3, 6)]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
187
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
188 or to compute a number of sines::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
189
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
190 >>> map( math.sin, (1,2,3,4))
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
191 [0.841470984808, 0.909297426826, 0.14112000806, -0.756802495308]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
192
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
193 The operation completes very quickly in such cases.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
194
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
195 Other examples include the ``join()`` and ``split()`` methods of string objects.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
196 For example if s1..s7 are large (10K+) strings then
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
197 ``"".join([s1,s2,s3,s4,s5,s6,s7])`` may be far faster than the more obvious
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
198 ``s1+s2+s3+s4+s5+s6+s7``, since the "summation" will compute many
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
199 subexpressions, whereas ``join()`` does all the copying in one pass. For
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
200 manipulating strings, use the ``replace()`` method on string objects. Use
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
201 regular expressions only when you're not dealing with constant string patterns.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
202 Consider using the string formatting operations ``string % tuple`` and ``string
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
203 % dictionary``.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
204
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
205 Be sure to use the :meth:`list.sort` builtin method to do sorting, and see the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
206 `sorting mini-HOWTO <http://wiki.python.org/moin/HowTo/Sorting>`_ for examples
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
207 of moderately advanced usage. :meth:`list.sort` beats other techniques for
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
208 sorting in all but the most extreme circumstances.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
209
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
210 Another common trick is to "push loops into functions or methods." For example
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
211 suppose you have a program that runs slowly and you use the profiler to
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
212 determine that a Python function ``ff()`` is being called lots of times. If you
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
213 notice that ``ff ()``::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
214
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
215 def ff(x):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
216 ... # do something with x computing result...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
217 return result
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
218
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
219 tends to be called in loops like::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
220
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
221 list = map(ff, oldlist)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
222
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
223 or::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
224
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
225 for x in sequence:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
226 value = ff(x)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
227 ... # do something with value...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
228
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
229 then you can often eliminate function call overhead by rewriting ``ff()`` to::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
230
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
231 def ffseq(seq):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
232 resultseq = []
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
233 for x in seq:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
234 ... # do something with x computing result...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
235 resultseq.append(result)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
236 return resultseq
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
237
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
238 and rewrite the two examples to ``list = ffseq(oldlist)`` and to::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
239
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
240 for value in ffseq(sequence):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
241 ... # do something with value...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
242
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
243 Single calls to ``ff(x)`` translate to ``ffseq([x])[0]`` with little penalty.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
244 Of course this technique is not always appropriate and there are other variants
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
245 which you can figure out.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
246
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
247 You can gain some performance by explicitly storing the results of a function or
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
248 method lookup into a local variable. A loop like::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
249
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
250 for key in token:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
251 dict[key] = dict.get(key, 0) + 1
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
252
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
253 resolves ``dict.get`` every iteration. If the method isn't going to change, a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
254 slightly faster implementation is::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
255
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
256 dict_get = dict.get # look up the method once
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
257 for key in token:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
258 dict[key] = dict_get(key, 0) + 1
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
259
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
260 Default arguments can be used to determine values once, at compile time instead
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
261 of at run time. This can only be done for functions or objects which will not
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
262 be changed during program execution, such as replacing ::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
263
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
264 def degree_sin(deg):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
265 return math.sin(deg * math.pi / 180.0)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
266
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
267 with ::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
268
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
269 def degree_sin(deg, factor=math.pi/180.0, sin=math.sin):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
270 return sin(deg * factor)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
271
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
272 Because this trick uses default arguments for terms which should not be changed,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
273 it should only be used when you are not concerned with presenting a possibly
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
274 confusing API to your users.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
275
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
276
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
277 Core Language
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
278 =============
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
279
57173
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
280 Why am I getting an UnboundLocalError when the variable has a value?
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
281 --------------------------------------------------------------------
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
282
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
283 It can be a surprise to get the UnboundLocalError in previously working
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
284 code when it is modified by adding an assignment statement somewhere in
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
285 the body of a function.
56890
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
286
57173
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
287 This code:
56890
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
288
57173
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
289 >>> x = 10
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
290 >>> def bar():
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
291 ... print x
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
292 >>> bar()
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
293 10
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
294
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
295 works, but this code:
56890
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
296
57173
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
297 >>> x = 10
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
298 >>> def foo():
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
299 ... print x
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
300 ... x += 1
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
301
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
302 results in an UnboundLocalError:
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
303
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
304 >>> foo()
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
305 Traceback (most recent call last):
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
306 ...
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
307 UnboundLocalError: local variable 'x' referenced before assignment
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
308
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
309 This is because when you make an assignment to a variable in a scope, that
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
310 variable becomes local to that scope and shadows any similarly named variable
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
311 in the outer scope. Since the last statement in foo assigns a new value to
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
312 ``x``, the compiler recognizes it as a local variable. Consequently when the
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
313 earlier ``print x`` attempts to print the uninitialized local variable and
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
314 an error results.
56890
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
315
57173
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
316 In the example above you can access the outer scope variable by declaring it
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
317 global:
56890
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
318
57173
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
319 >>> x = 10
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
320 >>> def foobar():
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
321 ... global x
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
322 ... print x
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
323 ... x += 1
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
324 >>> foobar()
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
325 10
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
326
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
327 This explicit declaration is required in order to remind you that (unlike the
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
328 superficially analogous situation with class and instance variables) you are
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
329 actually modifying the value of the variable in the outer scope:
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
330
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
331 >>> print x
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
332 11
56890
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
333
57173
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
334 In Python3, you can do a similar thing in a nested scope using the
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
335 :keyword:`nonlocal` keyword:
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
336
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
337 .. doctest::
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
338 :options: +SKIP
56890
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
339
57173
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
340 >>> def foo():
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
341 ... x = 10
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
342 ... def bar():
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
343 ... nonlocal x
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
344 ... print x
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
345 ... x += 1
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
346 ... bar()
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
347 ... print x
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
348 >>> foo()
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
349 10
867d2f2735b8 Update the FAQ entry that explains that assignments in the local scope
R. David Murray <rdmurray@bitdance.com>
parents: 56492
diff changeset
350 11
56890
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
351
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
352
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
353 What are the rules for local and global variables in Python?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
354 ------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
355
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
356 In Python, variables that are only referenced inside a function are implicitly
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
357 global. If a variable is assigned a new value anywhere within the function's
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
358 body, it's assumed to be a local. If a variable is ever assigned a new value
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
359 inside the function, the variable is implicitly local, and you need to
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
360 explicitly declare it as 'global'.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
361
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
362 Though a bit surprising at first, a moment's consideration explains this. On
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
363 one hand, requiring :keyword:`global` for assigned variables provides a bar
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
364 against unintended side-effects. On the other hand, if ``global`` was required
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
365 for all global references, you'd be using ``global`` all the time. You'd have
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
366 to declare as global every reference to a builtin function or to a component of
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
367 an imported module. This clutter would defeat the usefulness of the ``global``
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
368 declaration for identifying side-effects.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
369
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
370
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
371 How do I share global variables across modules?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
372 ------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
373
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
374 The canonical way to share information across modules within a single program is
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
375 to create a special module (often called config or cfg). Just import the config
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
376 module in all modules of your application; the module then becomes available as
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
377 a global name. Because there is only one instance of each module, any changes
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
378 made to the module object get reflected everywhere. For example:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
379
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
380 config.py::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
381
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
382 x = 0 # Default value of the 'x' configuration setting
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
383
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
384 mod.py::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
385
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
386 import config
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
387 config.x = 1
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
388
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
389 main.py::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
390
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
391 import config
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
392 import mod
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
393 print config.x
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
394
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
395 Note that using a module is also the basis for implementing the Singleton design
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
396 pattern, for the same reason.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
397
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
398
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
399 What are the "best practices" for using import in a module?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
400 -----------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
401
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
402 In general, don't use ``from modulename import *``. Doing so clutters the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
403 importer's namespace. Some people avoid this idiom even with the few modules
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
404 that were designed to be imported in this manner. Modules designed in this
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
405 manner include :mod:`Tkinter`, and :mod:`threading`.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
406
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
407 Import modules at the top of a file. Doing so makes it clear what other modules
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
408 your code requires and avoids questions of whether the module name is in scope.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
409 Using one import per line makes it easy to add and delete module imports, but
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
410 using multiple imports per line uses less screen space.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
411
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
412 It's good practice if you import modules in the following order:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
413
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
414 1. standard library modules -- e.g. ``sys``, ``os``, ``getopt``, ``re``)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
415 2. third-party library modules (anything installed in Python's site-packages
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
416 directory) -- e.g. mx.DateTime, ZODB, PIL.Image, etc.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
417 3. locally-developed modules
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
418
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
419 Never use relative package imports. If you're writing code that's in the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
420 ``package.sub.m1`` module and want to import ``package.sub.m2``, do not just
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
421 write ``import m2``, even though it's legal. Write ``from package.sub import
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
422 m2`` instead. Relative imports can lead to a module being initialized twice,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
423 leading to confusing bugs.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
424
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
425 It is sometimes necessary to move imports to a function or class to avoid
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
426 problems with circular imports. Gordon McMillan says:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
427
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
428 Circular imports are fine where both modules use the "import <module>" form
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
429 of import. They fail when the 2nd module wants to grab a name out of the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
430 first ("from module import name") and the import is at the top level. That's
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
431 because names in the 1st are not yet available, because the first module is
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
432 busy importing the 2nd.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
433
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
434 In this case, if the second module is only used in one function, then the import
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
435 can easily be moved into that function. By the time the import is called, the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
436 first module will have finished initializing, and the second module can do its
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
437 import.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
438
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
439 It may also be necessary to move imports out of the top level of code if some of
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
440 the modules are platform-specific. In that case, it may not even be possible to
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
441 import all of the modules at the top of the file. In this case, importing the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
442 correct modules in the corresponding platform-specific code is a good option.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
443
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
444 Only move imports into a local scope, such as inside a function definition, if
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
445 it's necessary to solve a problem such as avoiding a circular import or are
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
446 trying to reduce the initialization time of a module. This technique is
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
447 especially helpful if many of the imports are unnecessary depending on how the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
448 program executes. You may also want to move imports into a function if the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
449 modules are only ever used in that function. Note that loading a module the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
450 first time may be expensive because of the one time initialization of the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
451 module, but loading a module multiple times is virtually free, costing only a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
452 couple of dictionary lookups. Even if the module name has gone out of scope,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
453 the module is probably available in :data:`sys.modules`.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
454
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
455 If only instances of a specific class use a module, then it is reasonable to
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
456 import the module in the class's ``__init__`` method and then assign the module
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
457 to an instance variable so that the module is always available (via that
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
458 instance variable) during the life of the object. Note that to delay an import
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
459 until the class is instantiated, the import must be inside a method. Putting
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
460 the import inside the class but outside of any method still causes the import to
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
461 occur when the module is initialized.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
462
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
463
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
464 How can I pass optional or keyword parameters from one function to another?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
465 ---------------------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
466
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
467 Collect the arguments using the ``*`` and ``**`` specifiers in the function's
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
468 parameter list; this gives you the positional arguments as a tuple and the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
469 keyword arguments as a dictionary. You can then pass these arguments when
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
470 calling another function by using ``*`` and ``**``::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
471
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
472 def f(x, *args, **kwargs):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
473 ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
474 kwargs['width'] = '14.3c'
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
475 ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
476 g(x, *args, **kwargs)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
477
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
478 In the unlikely case that you care about Python versions older than 2.0, use
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
479 :func:`apply`::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
480
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
481 def f(x, *args, **kwargs):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
482 ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
483 kwargs['width'] = '14.3c'
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
484 ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
485 apply(g, (x,)+args, kwargs)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
486
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
487
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
488 How do I write a function with output parameters (call by reference)?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
489 ---------------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
490
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
491 Remember that arguments are passed by assignment in Python. Since assignment
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
492 just creates references to objects, there's no alias between an argument name in
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
493 the caller and callee, and so no call-by-reference per se. You can achieve the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
494 desired effect in a number of ways.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
495
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
496 1) By returning a tuple of the results::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
497
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
498 def func2(a, b):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
499 a = 'new-value' # a and b are local names
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
500 b = b + 1 # assigned to new objects
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
501 return a, b # return new values
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
502
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
503 x, y = 'old-value', 99
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
504 x, y = func2(x, y)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
505 print x, y # output: new-value 100
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
506
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
507 This is almost always the clearest solution.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
508
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
509 2) By using global variables. This isn't thread-safe, and is not recommended.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
510
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
511 3) By passing a mutable (changeable in-place) object::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
512
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
513 def func1(a):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
514 a[0] = 'new-value' # 'a' references a mutable list
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
515 a[1] = a[1] + 1 # changes a shared object
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
516
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
517 args = ['old-value', 99]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
518 func1(args)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
519 print args[0], args[1] # output: new-value 100
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
520
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
521 4) By passing in a dictionary that gets mutated::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
522
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
523 def func3(args):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
524 args['a'] = 'new-value' # args is a mutable dictionary
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
525 args['b'] = args['b'] + 1 # change it in-place
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
526
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
527 args = {'a':' old-value', 'b': 99}
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
528 func3(args)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
529 print args['a'], args['b']
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
530
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
531 5) Or bundle up values in a class instance::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
532
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
533 class callByRef:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
534 def __init__(self, **args):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
535 for (key, value) in args.items():
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
536 setattr(self, key, value)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
537
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
538 def func4(args):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
539 args.a = 'new-value' # args is a mutable callByRef
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
540 args.b = args.b + 1 # change object in-place
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
541
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
542 args = callByRef(a='old-value', b=99)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
543 func4(args)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
544 print args.a, args.b
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
545
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
546
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
547 There's almost never a good reason to get this complicated.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
548
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
549 Your best choice is to return a tuple containing the multiple results.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
550
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
551
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
552 How do you make a higher order function in Python?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
553 --------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
554
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
555 You have two choices: you can use nested scopes or you can use callable objects.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
556 For example, suppose you wanted to define ``linear(a,b)`` which returns a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
557 function ``f(x)`` that computes the value ``a*x+b``. Using nested scopes::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
558
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
559 def linear(a, b):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
560 def result(x):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
561 return a * x + b
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
562 return result
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
563
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
564 Or using a callable object::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
565
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
566 class linear:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
567
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
568 def __init__(self, a, b):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
569 self.a, self.b = a, b
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
570
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
571 def __call__(self, x):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
572 return self.a * x + self.b
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
573
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
574 In both cases, ::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
575
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
576 taxes = linear(0.3, 2)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
577
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
578 gives a callable object where ``taxes(10e6) == 0.3 * 10e6 + 2``.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
579
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
580 The callable object approach has the disadvantage that it is a bit slower and
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
581 results in slightly longer code. However, note that a collection of callables
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
582 can share their signature via inheritance::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
583
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
584 class exponential(linear):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
585 # __init__ inherited
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
586 def __call__(self, x):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
587 return self.a * (x ** self.b)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
588
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
589 Object can encapsulate state for several methods::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
590
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
591 class counter:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
592
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
593 value = 0
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
594
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
595 def set(self, x):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
596 self.value = x
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
597
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
598 def up(self):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
599 self.value = self.value + 1
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
600
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
601 def down(self):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
602 self.value = self.value - 1
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
603
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
604 count = counter()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
605 inc, dec, reset = count.up, count.down, count.set
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
606
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
607 Here ``inc()``, ``dec()`` and ``reset()`` act like functions which share the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
608 same counting variable.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
609
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
610
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
611 How do I copy an object in Python?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
612 ----------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
613
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
614 In general, try :func:`copy.copy` or :func:`copy.deepcopy` for the general case.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
615 Not all objects can be copied, but most can.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
616
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
617 Some objects can be copied more easily. Dictionaries have a :meth:`~dict.copy`
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
618 method::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
619
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
620 newdict = olddict.copy()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
621
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
622 Sequences can be copied by slicing::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
623
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
624 new_l = l[:]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
625
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
626
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
627 How can I find the methods or attributes of an object?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
628 ------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
629
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
630 For an instance x of a user-defined class, ``dir(x)`` returns an alphabetized
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
631 list of the names containing the instance attributes and methods and attributes
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
632 defined by its class.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
633
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
634
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
635 How can my code discover the name of an object?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
636 -----------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
637
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
638 Generally speaking, it can't, because objects don't really have names.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
639 Essentially, assignment always binds a name to a value; The same is true of
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
640 ``def`` and ``class`` statements, but in that case the value is a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
641 callable. Consider the following code::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
642
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
643 class A:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
644 pass
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
645
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
646 B = A
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
647
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
648 a = B()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
649 b = a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
650 print b
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
651 <__main__.A instance at 016D07CC>
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
652 print a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
653 <__main__.A instance at 016D07CC>
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
654
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
655 Arguably the class has a name: even though it is bound to two names and invoked
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
656 through the name B the created instance is still reported as an instance of
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
657 class A. However, it is impossible to say whether the instance's name is a or
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
658 b, since both names are bound to the same value.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
659
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
660 Generally speaking it should not be necessary for your code to "know the names"
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
661 of particular values. Unless you are deliberately writing introspective
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
662 programs, this is usually an indication that a change of approach might be
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
663 beneficial.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
664
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
665 In comp.lang.python, Fredrik Lundh once gave an excellent analogy in answer to
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
666 this question:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
667
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
668 The same way as you get the name of that cat you found on your porch: the cat
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
669 (object) itself cannot tell you its name, and it doesn't really care -- so
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
670 the only way to find out what it's called is to ask all your neighbours
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
671 (namespaces) if it's their cat (object)...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
672
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
673 ....and don't be surprised if you'll find that it's known by many names, or
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
674 no name at all!
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
675
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
676
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
677 What's up with the comma operator's precedence?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
678 -----------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
679
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
680 Comma is not an operator in Python. Consider this session::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
681
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
682 >>> "a" in "b", "a"
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
683 (False, '1')
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
684
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
685 Since the comma is not an operator, but a separator between expressions the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
686 above is evaluated as if you had entered::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
687
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
688 >>> ("a" in "b"), "a"
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
689
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
690 not::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
691
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
692 >>> "a" in ("5", "a")
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
693
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
694 The same is true of the various assignment operators (``=``, ``+=`` etc). They
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
695 are not truly operators but syntactic delimiters in assignment statements.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
696
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
697
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
698 Is there an equivalent of C's "?:" ternary operator?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
699 ----------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
700
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
701 Yes, this feature was added in Python 2.5. The syntax would be as follows::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
702
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
703 [on_true] if [expression] else [on_false]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
704
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
705 x, y = 50, 25
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
706
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
707 small = x if x < y else y
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
708
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
709 For versions previous to 2.5 the answer would be 'No'.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
710
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
711 .. XXX remove rest?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
712
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
713 In many cases you can mimic ``a ? b : c`` with ``a and b or c``, but there's a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
714 flaw: if *b* is zero (or empty, or ``None`` -- anything that tests false) then
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
715 *c* will be selected instead. In many cases you can prove by looking at the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
716 code that this can't happen (e.g. because *b* is a constant or has a type that
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
717 can never be false), but in general this can be a problem.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
718
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
719 Tim Peters (who wishes it was Steve Majewski) suggested the following solution:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
720 ``(a and [b] or [c])[0]``. Because ``[b]`` is a singleton list it is never
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
721 false, so the wrong path is never taken; then applying ``[0]`` to the whole
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
722 thing gets the *b* or *c* that you really wanted. Ugly, but it gets you there
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
723 in the rare cases where it is really inconvenient to rewrite your code using
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
724 'if'.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
725
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
726 The best course is usually to write a simple ``if...else`` statement. Another
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
727 solution is to implement the ``?:`` operator as a function::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
728
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
729 def q(cond, on_true, on_false):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
730 if cond:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
731 if not isfunction(on_true):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
732 return on_true
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
733 else:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
734 return apply(on_true)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
735 else:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
736 if not isfunction(on_false):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
737 return on_false
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
738 else:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
739 return apply(on_false)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
740
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
741 In most cases you'll pass b and c directly: ``q(a, b, c)``. To avoid evaluating
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
742 b or c when they shouldn't be, encapsulate them within a lambda function, e.g.:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
743 ``q(a, lambda: b, lambda: c)``.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
744
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
745 It has been asked *why* Python has no if-then-else expression. There are
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
746 several answers: many languages do just fine without one; it can easily lead to
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
747 less readable code; no sufficiently "Pythonic" syntax has been discovered; a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
748 search of the standard library found remarkably few places where using an
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
749 if-then-else expression would make the code more understandable.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
750
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
751 In 2002, :pep:`308` was written proposing several possible syntaxes and the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
752 community was asked to vote on the issue. The vote was inconclusive. Most
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
753 people liked one of the syntaxes, but also hated other syntaxes; many votes
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
754 implied that people preferred no ternary operator rather than having a syntax
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
755 they hated.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
756
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
757
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
758 Is it possible to write obfuscated one-liners in Python?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
759 --------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
760
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
761 Yes. Usually this is done by nesting :keyword:`lambda` within
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
762 :keyword:`lambda`. See the following three examples, due to Ulf Bartelt::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
763
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
764 # Primes < 1000
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
765 print filter(None,map(lambda y:y*reduce(lambda x,y:x*y!=0,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
766 map(lambda x,y=y:y%x,range(2,int(pow(y,0.5)+1))),1),range(2,1000)))
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
767
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
768 # First 10 Fibonacci numbers
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
769 print map(lambda x,f=lambda x,f:(x<=1) or (f(x-1,f)+f(x-2,f)): f(x,f),
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
770 range(10))
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
771
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
772 # Mandelbrot set
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
773 print (lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+y,map(lambda y,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
774 Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,Sy=Sy,L=lambda yc,Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,i=IM,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
775 Sx=Sx,Sy=Sy:reduce(lambda x,y:x+y,map(lambda x,xc=Ru,yc=yc,Ru=Ru,Ro=Ro,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
776 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
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
777 >=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(
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
778 64+F(Ru+x*(Ro-Ru)/Sx,yc,0,0,i)),range(Sx))):L(Iu+y*(Io-Iu)/Sy),range(Sy
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
779 ))))(-2.1, 0.7, -1.2, 1.2, 30, 80, 24)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
780 # \___ ___/ \___ ___/ | | |__ lines on screen
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
781 # V V | |______ columns on screen
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
782 # | | |__________ maximum of "iterations"
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
783 # | |_________________ range on y axis
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
784 # |____________________________ range on x axis
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
785
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
786 Don't try this at home, kids!
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
787
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
788
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
789 Numbers and strings
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
790 ===================
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
791
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
792 How do I specify hexadecimal and octal integers?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
793 ------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
794
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
795 To specify an octal digit, precede the octal value with a zero. For example, to
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
796 set the variable "a" to the octal value "10" (8 in decimal), type::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
797
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
798 >>> a = 010
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
799 >>> a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
800 8
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
801
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
802 Hexadecimal is just as easy. Simply precede the hexadecimal number with a zero,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
803 and then a lower or uppercase "x". Hexadecimal digits can be specified in lower
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
804 or uppercase. For example, in the Python interpreter::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
805
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
806 >>> a = 0xa5
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
807 >>> a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
808 165
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
809 >>> b = 0XB2
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
810 >>> b
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
811 178
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
812
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
813
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
814 Why does -22 / 10 return -3?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
815 ----------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
816
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
817 It's primarily driven by the desire that ``i % j`` have the same sign as ``j``.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
818 If you want that, and also want::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
819
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
820 i == (i / j) * j + (i % j)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
821
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
822 then integer division has to return the floor. C also requires that identity to
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
823 hold, and then compilers that truncate ``i / j`` need to make ``i % j`` have the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
824 same sign as ``i``.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
825
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
826 There are few real use cases for ``i % j`` when ``j`` is negative. When ``j``
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
827 is positive, there are many, and in virtually all of them it's more useful for
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
828 ``i % j`` to be ``>= 0``. If the clock says 10 now, what did it say 200 hours
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
829 ago? ``-190 % 12 == 2`` is useful; ``-190 % 12 == -10`` is a bug waiting to
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
830 bite.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
831
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
832
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
833 How do I convert a string to a number?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
834 --------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
835
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
836 For integers, use the built-in :func:`int` type constructor, e.g. ``int('144')
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
837 == 144``. Similarly, :func:`float` converts to floating-point,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
838 e.g. ``float('144') == 144.0``.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
839
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
840 By default, these interpret the number as decimal, so that ``int('0144') ==
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
841 144`` and ``int('0x144')`` raises :exc:`ValueError`. ``int(string, base)`` takes
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
842 the base to convert from as a second optional argument, so ``int('0x144', 16) ==
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
843 324``. If the base is specified as 0, the number is interpreted using Python's
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
844 rules: a leading '0' indicates octal, and '0x' indicates a hex number.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
845
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
846 Do not use the built-in function :func:`eval` if all you need is to convert
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
847 strings to numbers. :func:`eval` will be significantly slower and it presents a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
848 security risk: someone could pass you a Python expression that might have
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
849 unwanted side effects. For example, someone could pass
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
850 ``__import__('os').system("rm -rf $HOME")`` which would erase your home
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
851 directory.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
852
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
853 :func:`eval` also has the effect of interpreting numbers as Python expressions,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
854 so that e.g. ``eval('09')`` gives a syntax error because Python regards numbers
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
855 starting with '0' as octal (base 8).
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
856
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
857
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
858 How do I convert a number to a string?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
859 --------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
860
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
861 To convert, e.g., the number 144 to the string '144', use the built-in type
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
862 constructor :func:`str`. If you want a hexadecimal or octal representation, use
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
863 the built-in functions ``hex()`` or ``oct()``. For fancy formatting, use
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
864 :ref:`the % operator <string-formatting>` on strings, e.g. ``"%04d" % 144``
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
865 yields ``'0144'`` and ``"%.3f" % (1/3.0)`` yields ``'0.333'``. See the library
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
866 reference manual for details.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
867
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
868
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
869 How do I modify a string in place?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
870 ----------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
871
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
872 You can't, because strings are immutable. If you need an object with this
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
873 ability, try converting the string to a list or use the array module::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
874
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
875 >>> s = "Hello, world"
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
876 >>> a = list(s)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
877 >>> print a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
878 ['H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd']
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
879 >>> a[7:] = list("there!")
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
880 >>> ''.join(a)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
881 'Hello, there!'
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
882
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
883 >>> import array
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
884 >>> a = array.array('c', s)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
885 >>> print a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
886 array('c', 'Hello, world')
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
887 >>> a[0] = 'y' ; print a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
888 array('c', 'yello world')
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
889 >>> a.tostring()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
890 'yello, world'
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
891
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
892
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
893 How do I use strings to call functions/methods?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
894 -----------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
895
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
896 There are various techniques.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
897
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
898 * The best is to use a dictionary that maps strings to functions. The primary
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
899 advantage of this technique is that the strings do not need to match the names
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
900 of the functions. This is also the primary technique used to emulate a case
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
901 construct::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
902
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
903 def a():
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
904 pass
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
905
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
906 def b():
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
907 pass
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
908
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
909 dispatch = {'go': a, 'stop': b} # Note lack of parens for funcs
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
910
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
911 dispatch[get_input()]() # Note trailing parens to call function
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
912
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
913 * Use the built-in function :func:`getattr`::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
914
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
915 import foo
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
916 getattr(foo, 'bar')()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
917
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
918 Note that :func:`getattr` works on any object, including classes, class
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
919 instances, modules, and so on.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
920
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
921 This is used in several places in the standard library, like this::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
922
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
923 class Foo:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
924 def do_foo(self):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
925 ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
926
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
927 def do_bar(self):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
928 ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
929
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
930 f = getattr(foo_instance, 'do_' + opname)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
931 f()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
932
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
933
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
934 * Use :func:`locals` or :func:`eval` to resolve the function name::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
935
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
936 def myFunc():
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
937 print "hello"
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
938
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
939 fname = "myFunc"
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
940
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
941 f = locals()[fname]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
942 f()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
943
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
944 f = eval(fname)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
945 f()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
946
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
947 Note: Using :func:`eval` is slow and dangerous. If you don't have absolute
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
948 control over the contents of the string, someone could pass a string that
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
949 resulted in an arbitrary function being executed.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
950
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
951 Is there an equivalent to Perl's chomp() for removing trailing newlines from strings?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
952 -------------------------------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
953
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
954 Starting with Python 2.2, you can use ``S.rstrip("\r\n")`` to remove all
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
955 occurences of any line terminator from the end of the string ``S`` without
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
956 removing other trailing whitespace. If the string ``S`` represents more than
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
957 one line, with several empty lines at the end, the line terminators for all the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
958 blank lines will be removed::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
959
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
960 >>> lines = ("line 1 \r\n"
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
961 ... "\r\n"
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
962 ... "\r\n")
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
963 >>> lines.rstrip("\n\r")
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
964 "line 1 "
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
965
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
966 Since this is typically only desired when reading text one line at a time, using
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
967 ``S.rstrip()`` this way works well.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
968
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
969 For older versions of Python, There are two partial substitutes:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
970
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
971 - If you want to remove all trailing whitespace, use the ``rstrip()`` method of
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
972 string objects. This removes all trailing whitespace, not just a single
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
973 newline.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
974
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
975 - Otherwise, if there is only one line in the string ``S``, use
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
976 ``S.splitlines()[0]``.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
977
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
978
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
979 Is there a scanf() or sscanf() equivalent?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
980 ------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
981
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
982 Not as such.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
983
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
984 For simple input parsing, the easiest approach is usually to split the line into
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
985 whitespace-delimited words using the :meth:`~str.split` method of string objects
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
986 and then convert decimal strings to numeric values using :func:`int` or
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
987 :func:`float`. ``split()`` supports an optional "sep" parameter which is useful
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
988 if the line uses something other than whitespace as a separator.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
989
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
990 For more complicated input parsing, regular expressions more powerful than C's
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
991 :cfunc:`sscanf` and better suited for the task.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
992
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
993
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
994 What does 'UnicodeError: ASCII [decoding,encoding] error: ordinal not in range(128)' mean?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
995 ------------------------------------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
996
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
997 This error indicates that your Python installation can handle only 7-bit ASCII
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
998 strings. There are a couple ways to fix or work around the problem.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
999
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1000 If your programs must handle data in arbitrary character set encodings, the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1001 environment the application runs in will generally identify the encoding of the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1002 data it is handing you. You need to convert the input to Unicode data using
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1003 that encoding. For example, a program that handles email or web input will
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1004 typically find character set encoding information in Content-Type headers. This
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1005 can then be used to properly convert input data to Unicode. Assuming the string
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1006 referred to by ``value`` is encoded as UTF-8::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1007
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1008 value = unicode(value, "utf-8")
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1009
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1010 will return a Unicode object. If the data is not correctly encoded as UTF-8,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1011 the above call will raise a :exc:`UnicodeError` exception.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1012
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1013 If you only want strings converted to Unicode which have non-ASCII data, you can
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1014 try converting them first assuming an ASCII encoding, and then generate Unicode
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1015 objects if that fails::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1016
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1017 try:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1018 x = unicode(value, "ascii")
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1019 except UnicodeError:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1020 value = unicode(value, "utf-8")
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1021 else:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1022 # value was valid ASCII data
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1023 pass
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1024
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1025 It's possible to set a default encoding in a file called ``sitecustomize.py``
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1026 that's part of the Python library. However, this isn't recommended because
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1027 changing the Python-wide default encoding may cause third-party extension
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1028 modules to fail.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1029
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1030 Note that on Windows, there is an encoding known as "mbcs", which uses an
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1031 encoding specific to your current locale. In many cases, and particularly when
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1032 working with COM, this may be an appropriate default encoding to use.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1033
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1034
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1035 Sequences (Tuples/Lists)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1036 ========================
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1037
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1038 How do I convert between tuples and lists?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1039 ------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1040
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1041 The type constructor ``tuple(seq)`` converts any sequence (actually, any
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1042 iterable) into a tuple with the same items in the same order.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1043
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1044 For example, ``tuple([1, 2, 3])`` yields ``(1, 2, 3)`` and ``tuple('abc')``
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1045 yields ``('a', 'b', 'c')``. If the argument is a tuple, it does not make a copy
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1046 but returns the same object, so it is cheap to call :func:`tuple` when you
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1047 aren't sure that an object is already a tuple.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1048
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1049 The type constructor ``list(seq)`` converts any sequence or iterable into a list
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1050 with the same items in the same order. For example, ``list((1, 2, 3))`` yields
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1051 ``[1, 2, 3]`` and ``list('abc')`` yields ``['a', 'b', 'c']``. If the argument
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1052 is a list, it makes a copy just like ``seq[:]`` would.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1053
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1054
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1055 What's a negative index?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1056 ------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1057
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1058 Python sequences are indexed with positive numbers and negative numbers. For
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1059 positive numbers 0 is the first index 1 is the second index and so forth. For
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1060 negative indices -1 is the last index and -2 is the penultimate (next to last)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1061 index and so forth. Think of ``seq[-n]`` as the same as ``seq[len(seq)-n]``.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1062
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1063 Using negative indices can be very convenient. For example ``S[:-1]`` is all of
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1064 the string except for its last character, which is useful for removing the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1065 trailing newline from a string.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1066
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1067
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1068 How do I iterate over a sequence in reverse order?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1069 --------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1070
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1071 Use the :func:`reversed` builtin function, which is new in Python 2.4::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1072
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1073 for x in reversed(sequence):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1074 ... # do something with x...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1075
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1076 This won't touch your original sequence, but build a new copy with reversed
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1077 order to iterate over.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1078
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1079 With Python 2.3, you can use an extended slice syntax::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1080
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1081 for x in sequence[::-1]:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1082 ... # do something with x...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1083
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1084
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1085 How do you remove duplicates from a list?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1086 -----------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1087
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1088 See the Python Cookbook for a long discussion of many ways to do this:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1089
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1090 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1091
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1092 If you don't mind reordering the list, sort it and then scan from the end of the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1093 list, deleting duplicates as you go::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1094
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1095 if List:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1096 List.sort()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1097 last = List[-1]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1098 for i in range(len(List)-2, -1, -1):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1099 if last == List[i]:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1100 del List[i]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1101 else:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1102 last = List[i]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1103
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1104 If all elements of the list may be used as dictionary keys (i.e. they are all
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1105 hashable) this is often faster ::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1106
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1107 d = {}
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1108 for x in List:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1109 d[x] = x
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1110 List = d.values()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1111
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1112 In Python 2.5 and later, the following is possible instead::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1113
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1114 List = list(set(List))
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1115
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1116 This converts the list into a set, thereby removing duplicates, and then back
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1117 into a list.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1118
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1119
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1120 How do you make an array in Python?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1121 -----------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1122
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1123 Use a list::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1124
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1125 ["this", 1, "is", "an", "array"]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1126
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1127 Lists are equivalent to C or Pascal arrays in their time complexity; the primary
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1128 difference is that a Python list can contain objects of many different types.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1129
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1130 The ``array`` module also provides methods for creating arrays of fixed types
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1131 with compact representations, but they are slower to index than lists. Also
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1132 note that the Numeric extensions and others define array-like structures with
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1133 various characteristics as well.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1134
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1135 To get Lisp-style linked lists, you can emulate cons cells using tuples::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1136
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1137 lisp_list = ("like", ("this", ("example", None) ) )
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1138
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1139 If mutability is desired, you could use lists instead of tuples. Here the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1140 analogue of lisp car is ``lisp_list[0]`` and the analogue of cdr is
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1141 ``lisp_list[1]``. Only do this if you're sure you really need to, because it's
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1142 usually a lot slower than using Python lists.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1143
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1144
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1145 How do I create a multidimensional list?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1146 ----------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1147
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1148 You probably tried to make a multidimensional array like this::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1149
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1150 A = [[None] * 2] * 3
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1151
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1152 This looks correct if you print it::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1153
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1154 >>> A
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1155 [[None, None], [None, None], [None, None]]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1156
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1157 But when you assign a value, it shows up in multiple places:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1158
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1159 >>> A[0][0] = 5
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1160 >>> A
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1161 [[5, None], [5, None], [5, None]]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1162
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1163 The reason is that replicating a list with ``*`` doesn't create copies, it only
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1164 creates references to the existing objects. The ``*3`` creates a list
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1165 containing 3 references to the same list of length two. Changes to one row will
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1166 show in all rows, which is almost certainly not what you want.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1167
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1168 The suggested approach is to create a list of the desired length first and then
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1169 fill in each element with a newly created list::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1170
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1171 A = [None] * 3
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1172 for i in range(3):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1173 A[i] = [None] * 2
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1174
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1175 This generates a list containing 3 different lists of length two. You can also
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1176 use a list comprehension::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1177
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1178 w, h = 2, 3
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1179 A = [[None] * w for i in range(h)]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1180
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1181 Or, you can use an extension that provides a matrix datatype; `Numeric Python
56492
9f765118d9b9 Fix broken links found by "make linkcheck". scipy.org seems to be done right now, so I could not verify links going there.
Georg Brandl <georg@python.org>
parents: 56890
diff changeset
1182 <http://numpy.scipy.org/>`_ is the best known.
56890
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1183
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1184
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1185 How do I apply a method to a sequence of objects?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1186 -------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1187
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1188 Use a list comprehension::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1189
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1190 result = [obj.method() for obj in List]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1191
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1192 More generically, you can try the following function::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1193
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1194 def method_map(objects, method, arguments):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1195 """method_map([a,b], "meth", (1,2)) gives [a.meth(1,2), b.meth(1,2)]"""
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1196 nobjects = len(objects)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1197 methods = map(getattr, objects, [method]*nobjects)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1198 return map(apply, methods, [arguments]*nobjects)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1199
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1200
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1201 Dictionaries
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1202 ============
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1203
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1204 How can I get a dictionary to display its keys in a consistent order?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1205 ---------------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1206
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1207 You can't. Dictionaries store their keys in an unpredictable order, so the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1208 display order of a dictionary's elements will be similarly unpredictable.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1209
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1210 This can be frustrating if you want to save a printable version to a file, make
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1211 some changes and then compare it with some other printed dictionary. In this
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1212 case, use the ``pprint`` module to pretty-print the dictionary; the items will
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1213 be presented in order sorted by the key.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1214
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1215 A more complicated solution is to subclass ``UserDict.UserDict`` to create a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1216 ``SortedDict`` class that prints itself in a predictable order. Here's one
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1217 simpleminded implementation of such a class::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1218
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1219 import UserDict, string
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1220
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1221 class SortedDict(UserDict.UserDict):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1222 def __repr__(self):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1223 result = []
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1224 append = result.append
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1225 keys = self.data.keys()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1226 keys.sort()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1227 for k in keys:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1228 append("%s: %s" % (`k`, `self.data[k]`))
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1229 return "{%s}" % string.join(result, ", ")
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1230
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1231 __str__ = __repr__
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1232
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1233 This will work for many common situations you might encounter, though it's far
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1234 from a perfect solution. The largest flaw is that if some values in the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1235 dictionary are also dictionaries, their values won't be presented in any
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1236 particular order.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1237
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1238
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1239 I want to do a complicated sort: can you do a Schwartzian Transform in Python?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1240 ------------------------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1241
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1242 The technique, attributed to Randal Schwartz of the Perl community, sorts the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1243 elements of a list by a metric which maps each element to its "sort value". In
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1244 Python, just use the ``key`` argument for the ``sort()`` method::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1245
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1246 Isorted = L[:]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1247 Isorted.sort(key=lambda s: int(s[10:15]))
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1248
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1249 The ``key`` argument is new in Python 2.4, for older versions this kind of
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1250 sorting is quite simple to do with list comprehensions. To sort a list of
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1251 strings by their uppercase values::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1252
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1253 tmp1 = [(x.upper(), x) for x in L] # Schwartzian transform
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1254 tmp1.sort()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1255 Usorted = [x[1] for x in tmp1]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1256
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1257 To sort by the integer value of a subfield extending from positions 10-15 in
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1258 each string::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1259
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1260 tmp2 = [(int(s[10:15]), s) for s in L] # Schwartzian transform
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1261 tmp2.sort()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1262 Isorted = [x[1] for x in tmp2]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1263
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1264 Note that Isorted may also be computed by ::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1265
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1266 def intfield(s):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1267 return int(s[10:15])
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1268
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1269 def Icmp(s1, s2):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1270 return cmp(intfield(s1), intfield(s2))
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1271
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1272 Isorted = L[:]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1273 Isorted.sort(Icmp)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1274
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1275 but since this method calls ``intfield()`` many times for each element of L, it
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1276 is slower than the Schwartzian Transform.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1277
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1278
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1279 How can I sort one list by values from another list?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1280 ----------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1281
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1282 Merge them into a single list of tuples, sort the resulting list, and then pick
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1283 out the element you want. ::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1284
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1285 >>> list1 = ["what", "I'm", "sorting", "by"]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1286 >>> list2 = ["something", "else", "to", "sort"]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1287 >>> pairs = zip(list1, list2)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1288 >>> pairs
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1289 [('what', 'something'), ("I'm", 'else'), ('sorting', 'to'), ('by', 'sort')]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1290 >>> pairs.sort()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1291 >>> result = [ x[1] for x in pairs ]
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1292 >>> result
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1293 ['else', 'sort', 'to', 'something']
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1294
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1295 An alternative for the last step is::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1296
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1297 result = []
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1298 for p in pairs: result.append(p[1])
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1299
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1300 If you find this more legible, you might prefer to use this instead of the final
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1301 list comprehension. However, it is almost twice as slow for long lists. Why?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1302 First, the ``append()`` operation has to reallocate memory, and while it uses
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1303 some tricks to avoid doing that each time, it still has to do it occasionally,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1304 and that costs quite a bit. Second, the expression "result.append" requires an
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1305 extra attribute lookup, and third, there's a speed reduction from having to make
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1306 all those function calls.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1307
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1308
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1309 Objects
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1310 =======
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1311
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1312 What is a class?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1313 ----------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1314
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1315 A class is the particular object type created by executing a class statement.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1316 Class objects are used as templates to create instance objects, which embody
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1317 both the data (attributes) and code (methods) specific to a datatype.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1318
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1319 A class can be based on one or more other classes, called its base class(es). It
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1320 then inherits the attributes and methods of its base classes. This allows an
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1321 object model to be successively refined by inheritance. You might have a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1322 generic ``Mailbox`` class that provides basic accessor methods for a mailbox,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1323 and subclasses such as ``MboxMailbox``, ``MaildirMailbox``, ``OutlookMailbox``
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1324 that handle various specific mailbox formats.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1325
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1326
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1327 What is a method?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1328 -----------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1329
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1330 A method is a function on some object ``x`` that you normally call as
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1331 ``x.name(arguments...)``. Methods are defined as functions inside the class
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1332 definition::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1333
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1334 class C:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1335 def meth (self, arg):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1336 return arg * 2 + self.attribute
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1337
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1338
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1339 What is self?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1340 -------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1341
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1342 Self is merely a conventional name for the first argument of a method. A method
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1343 defined as ``meth(self, a, b, c)`` should be called as ``x.meth(a, b, c)`` for
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1344 some instance ``x`` of the class in which the definition occurs; the called
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1345 method will think it is called as ``meth(x, a, b, c)``.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1346
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1347 See also :ref:`why-self`.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1348
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1349
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1350 How do I check if an object is an instance of a given class or of a subclass of it?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1351 -----------------------------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1352
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1353 Use the built-in function ``isinstance(obj, cls)``. You can check if an object
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1354 is an instance of any of a number of classes by providing a tuple instead of a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1355 single class, e.g. ``isinstance(obj, (class1, class2, ...))``, and can also
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1356 check whether an object is one of Python's built-in types, e.g.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1357 ``isinstance(obj, str)`` or ``isinstance(obj, (int, long, float, complex))``.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1358
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1359 Note that most programs do not use :func:`isinstance` on user-defined classes
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1360 very often. If you are developing the classes yourself, a more proper
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1361 object-oriented style is to define methods on the classes that encapsulate a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1362 particular behaviour, instead of checking the object's class and doing a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1363 different thing based on what class it is. For example, if you have a function
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1364 that does something::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1365
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1366 def search (obj):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1367 if isinstance(obj, Mailbox):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1368 # ... code to search a mailbox
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1369 elif isinstance(obj, Document):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1370 # ... code to search a document
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1371 elif ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1372
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1373 A better approach is to define a ``search()`` method on all the classes and just
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1374 call it::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1375
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1376 class Mailbox:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1377 def search(self):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1378 # ... code to search a mailbox
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1379
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1380 class Document:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1381 def search(self):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1382 # ... code to search a document
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1383
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1384 obj.search()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1385
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1386
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1387 What is delegation?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1388 -------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1389
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1390 Delegation is an object oriented technique (also called a design pattern).
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1391 Let's say you have an object ``x`` and want to change the behaviour of just one
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1392 of its methods. You can create a new class that provides a new implementation
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1393 of the method you're interested in changing and delegates all other methods to
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1394 the corresponding method of ``x``.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1395
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1396 Python programmers can easily implement delegation. For example, the following
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1397 class implements a class that behaves like a file but converts all written data
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1398 to uppercase::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1399
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1400 class UpperOut:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1401
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1402 def __init__(self, outfile):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1403 self._outfile = outfile
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1404
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1405 def write(self, s):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1406 self._outfile.write(s.upper())
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1407
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1408 def __getattr__(self, name):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1409 return getattr(self._outfile, name)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1410
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1411 Here the ``UpperOut`` class redefines the ``write()`` method to convert the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1412 argument string to uppercase before calling the underlying
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1413 ``self.__outfile.write()`` method. All other methods are delegated to the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1414 underlying ``self.__outfile`` object. The delegation is accomplished via the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1415 ``__getattr__`` method; consult :ref:`the language reference <attribute-access>`
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1416 for more information about controlling attribute access.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1417
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1418 Note that for more general cases delegation can get trickier. When attributes
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1419 must be set as well as retrieved, the class must define a :meth:`__setattr__`
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1420 method too, and it must do so carefully. The basic implementation of
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1421 :meth:`__setattr__` is roughly equivalent to the following::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1422
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1423 class X:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1424 ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1425 def __setattr__(self, name, value):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1426 self.__dict__[name] = value
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1427 ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1428
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1429 Most :meth:`__setattr__` implementations must modify ``self.__dict__`` to store
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1430 local state for self without causing an infinite recursion.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1431
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1432
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1433 How do I call a method defined in a base class from a derived class that overrides it?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1434 --------------------------------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1435
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1436 If you're using new-style classes, use the built-in :func:`super` function::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1437
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1438 class Derived(Base):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1439 def meth (self):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1440 super(Derived, self).meth()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1441
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1442 If you're using classic classes: For a class definition such as ``class
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1443 Derived(Base): ...`` you can call method ``meth()`` defined in ``Base`` (or one
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1444 of ``Base``'s base classes) as ``Base.meth(self, arguments...)``. Here,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1445 ``Base.meth`` is an unbound method, so you need to provide the ``self``
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1446 argument.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1447
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1448
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1449 How can I organize my code to make it easier to change the base class?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1450 ----------------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1451
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1452 You could define an alias for the base class, assign the real base class to it
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1453 before your class definition, and use the alias throughout your class. Then all
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1454 you have to change is the value assigned to the alias. Incidentally, this trick
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1455 is also handy if you want to decide dynamically (e.g. depending on availability
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1456 of resources) which base class to use. Example::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1457
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1458 BaseAlias = <real base class>
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1459
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1460 class Derived(BaseAlias):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1461 def meth(self):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1462 BaseAlias.meth(self)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1463 ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1464
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1465
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1466 How do I create static class data and static class methods?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1467 -----------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1468
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1469 Static data (in the sense of C++ or Java) is easy; static methods (again in the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1470 sense of C++ or Java) are not supported directly.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1471
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1472 For static data, simply define a class attribute. To assign a new value to the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1473 attribute, you have to explicitly use the class name in the assignment::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1474
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1475 class C:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1476 count = 0 # number of times C.__init__ called
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1477
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1478 def __init__(self):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1479 C.count = C.count + 1
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1480
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1481 def getcount(self):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1482 return C.count # or return self.count
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1483
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1484 ``c.count`` also refers to ``C.count`` for any ``c`` such that ``isinstance(c,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1485 C)`` holds, unless overridden by ``c`` itself or by some class on the base-class
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1486 search path from ``c.__class__`` back to ``C``.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1487
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1488 Caution: within a method of C, an assignment like ``self.count = 42`` creates a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1489 new and unrelated instance vrbl named "count" in ``self``'s own dict. Rebinding
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1490 of a class-static data name must always specify the class whether inside a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1491 method or not::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1492
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1493 C.count = 314
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1494
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1495 Static methods are possible since Python 2.2::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1496
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1497 class C:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1498 def static(arg1, arg2, arg3):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1499 # No 'self' parameter!
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1500 ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1501 static = staticmethod(static)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1502
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1503 With Python 2.4's decorators, this can also be written as ::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1504
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1505 class C:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1506 @staticmethod
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1507 def static(arg1, arg2, arg3):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1508 # No 'self' parameter!
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1509 ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1510
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1511 However, a far more straightforward way to get the effect of a static method is
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1512 via a simple module-level function::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1513
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1514 def getcount():
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1515 return C.count
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1516
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1517 If your code is structured so as to define one class (or tightly related class
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1518 hierarchy) per module, this supplies the desired encapsulation.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1519
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1520
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1521 How can I overload constructors (or methods) in Python?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1522 -------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1523
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1524 This answer actually applies to all methods, but the question usually comes up
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1525 first in the context of constructors.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1526
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1527 In C++ you'd write
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1528
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1529 .. code-block:: c
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1530
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1531 class C {
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1532 C() { cout << "No arguments\n"; }
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1533 C(int i) { cout << "Argument is " << i << "\n"; }
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1534 }
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1535
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1536 In Python you have to write a single constructor that catches all cases using
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1537 default arguments. For example::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1538
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1539 class C:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1540 def __init__(self, i=None):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1541 if i is None:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1542 print "No arguments"
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1543 else:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1544 print "Argument is", i
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1545
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1546 This is not entirely equivalent, but close enough in practice.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1547
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1548 You could also try a variable-length argument list, e.g. ::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1549
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1550 def __init__(self, *args):
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1551 ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1552
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1553 The same approach works for all method definitions.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1554
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1555
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1556 I try to use __spam and I get an error about _SomeClassName__spam.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1557 ------------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1558
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1559 Variable names with double leading underscores are "mangled" to provide a simple
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1560 but effective way to define class private variables. Any identifier of the form
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1561 ``__spam`` (at least two leading underscores, at most one trailing underscore)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1562 is textually replaced with ``_classname__spam``, where ``classname`` is the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1563 current class name with any leading underscores stripped.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1564
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1565 This doesn't guarantee privacy: an outside user can still deliberately access
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1566 the "_classname__spam" attribute, and private values are visible in the object's
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1567 ``__dict__``. Many Python programmers never bother to use private variable
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1568 names at all.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1569
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1570
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1571 My class defines __del__ but it is not called when I delete the object.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1572 -----------------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1573
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1574 There are several possible reasons for this.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1575
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1576 The del statement does not necessarily call :meth:`__del__` -- it simply
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1577 decrements the object's reference count, and if this reaches zero
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1578 :meth:`__del__` is called.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1579
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1580 If your data structures contain circular links (e.g. a tree where each child has
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1581 a parent reference and each parent has a list of children) the reference counts
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1582 will never go back to zero. Once in a while Python runs an algorithm to detect
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1583 such cycles, but the garbage collector might run some time after the last
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1584 reference to your data structure vanishes, so your :meth:`__del__` method may be
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1585 called at an inconvenient and random time. This is inconvenient if you're trying
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1586 to reproduce a problem. Worse, the order in which object's :meth:`__del__`
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1587 methods are executed is arbitrary. You can run :func:`gc.collect` to force a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1588 collection, but there *are* pathological cases where objects will never be
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1589 collected.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1590
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1591 Despite the cycle collector, it's still a good idea to define an explicit
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1592 ``close()`` method on objects to be called whenever you're done with them. The
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1593 ``close()`` method can then remove attributes that refer to subobjecs. Don't
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1594 call :meth:`__del__` directly -- :meth:`__del__` should call ``close()`` and
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1595 ``close()`` should make sure that it can be called more than once for the same
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1596 object.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1597
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1598 Another way to avoid cyclical references is to use the :mod:`weakref` module,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1599 which allows you to point to objects without incrementing their reference count.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1600 Tree data structures, for instance, should use weak references for their parent
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1601 and sibling references (if they need them!).
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1602
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1603 If the object has ever been a local variable in a function that caught an
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1604 expression in an except clause, chances are that a reference to the object still
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1605 exists in that function's stack frame as contained in the stack trace.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1606 Normally, calling :func:`sys.exc_clear` will take care of this by clearing the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1607 last recorded exception.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1608
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1609 Finally, if your :meth:`__del__` method raises an exception, a warning message
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1610 is printed to :data:`sys.stderr`.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1611
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1612
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1613 How do I get a list of all instances of a given class?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1614 ------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1615
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1616 Python does not keep track of all instances of a class (or of a built-in type).
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1617 You can program the class's constructor to keep track of all instances by
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1618 keeping a list of weak references to each instance.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1619
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1620
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1621 Modules
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1622 =======
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1623
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1624 How do I create a .pyc file?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1625 ----------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1626
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1627 When a module is imported for the first time (or when the source is more recent
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1628 than the current compiled file) a ``.pyc`` file containing the compiled code
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1629 should be created in the same directory as the ``.py`` file.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1630
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1631 One reason that a ``.pyc`` file may not be created is permissions problems with
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1632 the directory. This can happen, for example, if you develop as one user but run
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1633 as another, such as if you are testing with a web server. Creation of a .pyc
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1634 file is automatic if you're importing a module and Python has the ability
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1635 (permissions, free space, etc...) to write the compiled module back to the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1636 directory.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1637
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1638 Running Python on a top level script is not considered an import and no ``.pyc``
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1639 will be created. For example, if you have a top-level module ``abc.py`` that
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1640 imports another module ``xyz.py``, when you run abc, ``xyz.pyc`` will be created
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1641 since xyz is imported, but no ``abc.pyc`` file will be created since ``abc.py``
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1642 isn't being imported.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1643
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1644 If you need to create abc.pyc -- that is, to create a .pyc file for a module
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1645 that is not imported -- you can, using the :mod:`py_compile` and
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1646 :mod:`compileall` modules.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1647
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1648 The :mod:`py_compile` module can manually compile any module. One way is to use
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1649 the ``compile()`` function in that module interactively::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1650
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1651 >>> import py_compile
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1652 >>> py_compile.compile('abc.py')
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1653
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1654 This will write the ``.pyc`` to the same location as ``abc.py`` (or you can
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1655 override that with the optional parameter ``cfile``).
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1656
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1657 You can also automatically compile all files in a directory or directories using
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1658 the :mod:`compileall` module. You can do it from the shell prompt by running
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1659 ``compileall.py`` and providing the path of a directory containing Python files
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1660 to compile::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1661
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1662 python -m compileall .
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1663
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1664
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1665 How do I find the current module name?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1666 --------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1667
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1668 A module can find out its own module name by looking at the predefined global
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1669 variable ``__name__``. If this has the value ``'__main__'``, the program is
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1670 running as a script. Many modules that are usually used by importing them also
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1671 provide a command-line interface or a self-test, and only execute this code
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1672 after checking ``__name__``::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1673
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1674 def main():
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1675 print 'Running test...'
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1676 ...
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1677
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1678 if __name__ == '__main__':
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1679 main()
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1680
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1681
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1682 How can I have modules that mutually import each other?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1683 -------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1684
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1685 Suppose you have the following modules:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1686
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1687 foo.py::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1688
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1689 from bar import bar_var
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1690 foo_var = 1
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1691
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1692 bar.py::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1693
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1694 from foo import foo_var
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1695 bar_var = 2
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1696
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1697 The problem is that the interpreter will perform the following steps:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1698
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1699 * main imports foo
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1700 * Empty globals for foo are created
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1701 * foo is compiled and starts executing
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1702 * foo imports bar
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1703 * Empty globals for bar are created
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1704 * bar is compiled and starts executing
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1705 * bar imports foo (which is a no-op since there already is a module named foo)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1706 * bar.foo_var = foo.foo_var
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1707
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1708 The last step fails, because Python isn't done with interpreting ``foo`` yet and
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1709 the global symbol dictionary for ``foo`` is still empty.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1710
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1711 The same thing happens when you use ``import foo``, and then try to access
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1712 ``foo.foo_var`` in global code.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1713
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1714 There are (at least) three possible workarounds for this problem.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1715
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1716 Guido van Rossum recommends avoiding all uses of ``from <module> import ...``,
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1717 and placing all code inside functions. Initializations of global variables and
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1718 class variables should use constants or built-in functions only. This means
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1719 everything from an imported module is referenced as ``<module>.<name>``.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1720
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1721 Jim Roskind suggests performing steps in the following order in each module:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1722
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1723 * exports (globals, functions, and classes that don't need imported base
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1724 classes)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1725 * ``import`` statements
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1726 * active code (including globals that are initialized from imported values).
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1727
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1728 van Rossum doesn't like this approach much because the imports appear in a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1729 strange place, but it does work.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1730
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1731 Matthias Urlichs recommends restructuring your code so that the recursive import
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1732 is not necessary in the first place.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1733
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1734 These solutions are not mutually exclusive.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1735
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1736
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1737 __import__('x.y.z') returns <module 'x'>; how do I get z?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1738 ---------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1739
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1740 Try::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1741
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1742 __import__('x.y.z').y.z
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1743
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1744 For more realistic situations, you may have to do something like ::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1745
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1746 m = __import__(s)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1747 for i in s.split(".")[1:]:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1748 m = getattr(m, i)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1749
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1750 See :mod:`importlib` for a convenience function called
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1751 :func:`~importlib.import_module`.
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1752
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1753
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1754
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1755 When I edit an imported module and reimport it, the changes don't show up. Why does this happen?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1756 -------------------------------------------------------------------------------------------------
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1757
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1758 For reasons of efficiency as well as consistency, Python only reads the module
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1759 file on the first time a module is imported. If it didn't, in a program
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1760 consisting of many modules where each one imports the same basic module, the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1761 basic module would be parsed and re-parsed many times. To force rereading of a
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1762 changed module, do this::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1763
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1764 import modname
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1765 reload(modname)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1766
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1767 Warning: this technique is not 100% fool-proof. In particular, modules
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1768 containing statements like ::
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1769
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1770 from modname import some_objects
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1771
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1772 will continue to work with the old version of the imported objects. If the
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1773 module contains class definitions, existing class instances will *not* be
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1774 updated to use the new class definition. This can result in the following
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1775 paradoxical behaviour:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1776
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1777 >>> import cls
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1778 >>> c = cls.C() # Create an instance of C
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1779 >>> reload(cls)
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1780 <module 'cls' from 'cls.pyc'>
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1781 >>> isinstance(c, cls.C) # isinstance is false?!?
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1782 False
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1783
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1784 The nature of the problem is made clear if you print out the class objects:
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1785
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1786 >>> c.__class__
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1787 <class cls.C at 0x7352a0>
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1788 >>> cls.C
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1789 <class cls.C at 0x4198d0>
cef5cb270fdf Merged revisions 75374 via svnmerge from
Georg Brandl <georg@python.org>
parents:
diff changeset
1790