File: 259.html

package info (click to toggle)
python-casacore 3.7.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,488 kB
  • sloc: python: 4,170; cpp: 1,549; makefile: 67
file content (418 lines) | stat: -rw-r--r-- 21,887 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  
  "http://www.w3.org/TR/html4/loose.dtd">  
<html > 
<head><title>NOTE 259: pyrap binding to casacore</title> 
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> 
<meta name="generator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/)"> 
<meta name="originator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/)"> 
<!-- html --> 
<meta name="src" content="259.tex"> 
<meta name="date" content="2007-11-14 15:18:00"> 
<link rel="stylesheet" type="text/css" href="259.css"> 
</head><body 
>
   <div class="maketitle">
                                                                     

                                                                     
                                                                     

                                                                     

<h2 class="titleHead">NOTE 259: pyrap binding to casacore</h2>
<div class="author" ><span 
class="cmr-12">Ger van Diepen, ASTRON Dwingeloo</span></div>
<br />
<div class="date" ><span 
class="cmr-12">November 10, 2006</span></div>
   </div><table 
class="abstract"><tr><td 
>
<div class="center" 
>
<!--l. 12--><p class="noindent" >
<!--l. 12--><p class="noindent" ><span 
class="cmbx-10">Abstract</span></div>
     <!--l. 13--><p class="indent" >    <span 
class="cmr-10">pyrap is a Python binding to casacore classes using Boost.Python.</span>
     <span 
class="cmr-10">It consists of a set of standard converters and bindings to the classes.</span>
     <span 
class="cmr-10">As much as possible the bindings are the same as in glish.</span>
</td></tr></table>
   <h3 class="likesectionHead"><a 
 id="x1-1000"></a>Contents</h3>
   <div class="tableofcontents">
   <span class="sectionToc" >1 <a 
href="#x1-20001" id="QQ2-1-2">Introduction</a></span>
<br />   <span class="sectionToc" >2 <a 
href="#x1-30002" id="QQ2-1-3">Converters</a></span>
<br />   &#x00A0;<span class="subsectionToc" >2.1 <a 
href="#x1-40002.1" id="QQ2-1-4">Array conversion to/from numpy and numarray</a></span>
<br />   <span class="sectionToc" >3 <a 
href="#x1-50003" id="QQ2-1-5">Class wrappers</a></span>
<br />   &#x00A0;<span class="subsectionToc" >3.1 <a 
href="#x1-60003.1" id="QQ2-1-6">More complicated wrappers</a></span>
<br />   &#x00A0;<span class="subsectionToc" >3.2 <a 
href="#x1-70003.2" id="QQ2-1-7">Combining multiple classes</a></span>
<br />   <span class="sectionToc" >4 <a 
href="#x1-80004" id="QQ2-1-8">Python specifics</a></span>
   </div>
                                                                     

                                                                     
   <h3 class="sectionHead"><span class="titlemark">1   </span> <a 
 id="x1-20001"></a>Introduction</h3>
<!--l. 2--><p class="noindent" >Since long glish bindings to the <a 
href="http://casacore.googlecode.com" >casacore</a> system have been in place. Quite
recently Python bindings have been created in the general casapy framework
using tools like CCMTools, Xerces, Xalan, and IDL. Albeit very flexible, it is
quite complicated and it is not straightforward to build on other systems than
RedHat and OS-X.
<!--l. 8--><p class="indent" >   Therefore an attempt has been made to make a simpler Python binding using
<a 
href="http://www.boost.org/libs/python/doc" >Boost.Python</a>. This proved to be very easy and succesful. The binding consists of
two parts:
     <ul class="itemize1">
     <li class="itemize">Converters to translate objects between Python and C++.
     </li>
     <li class="itemize">Class wrappers to map a C++ class and its functions to Python.</li></ul>
<!--l. 16--><p class="noindent" >The Python numarray and numpy (version 1.0 or higher) packages are supported. At
build time one can choose which ones should be used.
<!--l. 19--><p class="noindent" >
   <h3 class="sectionHead"><span class="titlemark">2   </span> <a 
 id="x1-30002"></a>Converters</h3>
<!--l. 20--><p class="noindent" >Boost.Python offers a nice way to convert objects to and from Python. Ralf W.
Grosse-Kunstleve <span 
class="cmtt-10x-x-109">&#x003C;rwgk@yahoo.com&#x003E; </span>of <a 
href="http://www.lbl.gov" >Lawrence Berkeley National Laboratory</a>
has built converters for standard STL containers. This has been extended to
convert to/from other objects.
<br class="newline" />The following C++ objects are currently supported:
     <ul class="itemize1">
     <li class="itemize">scalars (bool, integer, real, complex)
     </li>
     <li class="itemize"><span 
class="cmtt-10x-x-109">std::string</span>
     </li>
     <li class="itemize"><span 
class="cmtt-10x-x-109">casa::String</span>
     </li>
     <li class="itemize"><span 
class="cmtt-10x-x-109">std::vector&#x003C;T&#x003E;</span>
     </li>
     <li class="itemize"><span 
class="cmtt-10x-x-109">casa::Vector&#x003C;T&#x003E;</span>
                                                                     

                                                                     
     </li>
     <li class="itemize"><span 
class="cmtt-10x-x-109">casa::IPosition</span>
     </li>
     <li class="itemize"><span 
class="cmtt-10x-x-109">casa::Record</span>
     </li>
     <li class="itemize"><span 
class="cmtt-10x-x-109">casa::ValueHolder</span>
     </li>
     <li class="itemize">exceptions (<span 
class="cmtt-10x-x-109">casa::IterError </span>and <span 
class="cmtt-10x-x-109">std::exception</span>)</li></ul>
<!--l. 37--><p class="noindent" >These C++ objects can usually be created from several types of Python objects and
are converted to a specific Python object.
     <ul class="itemize1">
     <li class="itemize">A vector or IPosition object is converted to a Python list.
     <br class="newline" />It can be constructed from the following Python objects:
          <ul class="itemize2">
          <li class="itemize">scalar
          </li>
          <li class="itemize">list or tuple
          </li>
          <li class="itemize">numarray scalar or 1-dim array
          </li>
          <li class="itemize">numpy scalar or 1-dim array</li></ul>
     <!--l. 49--><p class="noindent" >Note that a list or tuple of arbitrary objects can be given. For example, it is
     possible to get a <span 
class="cmtt-10x-x-109">Vector&#x003C;TableProxy&#x003E; </span>from Python.
     </li>
     <li class="itemize">A casa::Record is mapped to a Python dict.
     </li>
     <li class="itemize">Every C++ exception is mapped to a Python <span 
class="cmtt-10x-x-109">RunTimeError </span>exception.
     However, <span 
class="cmtt-10x-x-109">casa::IterError </span>is special and is mapped to an end-of-iteration
     exception (<span 
class="cmtt-10x-x-109">StopIteration</span>) in Python.
     </li>
     <li class="itemize">A casa::ValueHolder is a special <a 
href="http://casacore.googlecode.com" >casacore</a> object that can hold a record
     or a scalar value or n-dim array of many types (bool, numeric,
                                                                     

                                                                     
     string). It is meant to conceal the actual type which is useful in
     functions that can accept a variety of types (like <span 
class="cmtt-10x-x-109">getcell </span>in the table
     binding).
     <br class="newline" />Converting a ValueHolder to Python creates the appropriate Python scalar,
     array, or dict object. When converting from Python to ValueHolder,
     the appropriate internal ValueHolder value is constructed; a list,
     tuple, and array object are converted to an <a 
href="http://casacore.googlecode.com" >casacore</a> array in the
     ValueHolder.</li></ul>
<!--l. 69--><p class="noindent" >It means there is no direct Array conversion to/from Python. A ValueHolder
object is always needed to do the conversion. Note that this is a cheap
operation, as it uses Array reference semantics. ValueHolder has functions to
convert between types, so one can get out an Array with the required
type.
<!--l. 75--><p class="noindent" >
   <h4 class="subsectionHead"><span class="titlemark">2.1   </span> <a 
 id="x1-40002.1"></a>Array conversion to/from numpy and numarray</h4>
<!--l. 76--><p class="noindent" ><a 
href="http://casacore.googlecode.com" >casacore</a> arrays are kept in Fortran-order, while Python arrays are kept in
C-order. It was felt that the Python interface should be as pythonic as possible.
Therefore it was decided that the array axes are reversed when converting
to/from Python. The values in an IPosition object (describing shape or position)
are also reversed when converting to/from Python.
<br class="newline" />Note that although numarray and numpy have Fortran-array provisions by
setting the appropriate internal strides, they do not really support them. When
adding, for instance, the scalar value 0 to a Fortran-array, the result
is a transposed version of the original (which can be a quite expensive
operation).
<!--l. 88--><p class="indent" >   A function binding could be such that shape information is passed via, say, a
<span 
class="cmtt-10x-x-109">Record </span>and not via an <span 
class="cmtt-10x-x-109">IPosition </span>object. In that case its values are
not reversed automatically, so the programmer is responsible for doing
it.
<!--l. 94--><p class="indent" >   An <a 
href="http://casacore.googlecode.com" >casacore</a> array is returned to Python as an array object containing a copy
of the <a 
href="http://casacore.googlecode.com" >casacore</a> array data. If pyrap has been built with support for only one
Python array package (numpy or numarray), it is clear which array type is
returned. If support for both packages has been built in, by default an array of
the imported package is returned. If both or no array packages have been
imported, a numpy array is returned.
<br class="newline" />Note that there is no support for the old Numeric package.
<!--l. 103--><p class="indent" >   An <a 
href="http://casacore.googlecode.com" >casacore</a> array constructed from a Python array is regarded as a
                                                                     

                                                                     
temporary object. So if possible, the <a 
href="http://casacore.googlecode.com" >casacore</a> array refers to the Python array
data to avoid a needless copy. This is not possible if the element size in Python
differs from <a 
href="http://casacore.googlecode.com" >casacore</a>. It is also not possible if the Python array is not
contiguous (or not aligned or byte swapped). In those cases a copy is
made.
<!--l. 110--><p class="indent" >   A few more numarray/numpy specific issues are dealt with:
     <ul class="itemize1">
     <li class="itemize">An empty N-dim <a 
href="http://casacore.googlecode.com" >casacore</a> array (i.e. an array containing no elements)
     is returned as an empty N-dim Python array. If the dimensionality
     is  zero,  it  is  returned  as  an  empty  1-dim  array,  to  prevent
     numarray/numpy from treating it as a scalar value.
     </li>
     <li class="itemize">In  numarray  <span 
class="cmtt-10x-x-109">array() </span>results  in  <span 
class="cmtt-10x-x-109">Py</span><span 
class="cmtt-10x-x-109">_None</span>.  This  is  accepted  by  the
     converters as an empty 1-dim array.
     </li>
     <li class="itemize">Empty arrays can be constructed in Python using empty lists. For
     example, <span 
class="cmtt-10x-x-109">array([[]]) </span>results in an empty 2-dim array. The converters
     accept such empty N-dim Python arrays. The type of an empty array
     is set to Int by numarray and to Double by numpy.
     </li>
     <li class="itemize">Because the type of an empty Python array cannot easily be set, the
     converters can convert an empty integer or real array to any type.
     </li>
     <li class="itemize">The converters accept a numpy string array. However, it is returned
     to Python as the special <span 
class="cmtt-10x-x-109">dict </span>object described above.</li></ul>
<!--l. 128--><p class="noindent" >
   <h3 class="sectionHead"><span class="titlemark">3   </span> <a 
 id="x1-50003"></a>Class wrappers</h3>
<!--l. 129--><p class="noindent" >Usually a binding to an existing Proxy class is made, for example <span 
class="cmtt-10x-x-109">TableProxy</span>,
which should be the same class used in the glish-binding. For a simple binding,
only some simple C++ code has to be written in pyrap_xx/src/pyxx.cc, where
XX is the name of the package/class.
                                                                     

                                                                     
   <table 
class="verbatim"><tr class="verbatim"><td 
class="verbatim"><div class="verbatim">
//&#x00A0;Include&#x00A0;files&#x00A0;for&#x00A0;converters&#x00A0;being&#x00A0;used.
&#x00A0;<br />#include&#x00A0;&#x003C;casacore/python/Converters/PycExcp.h&#x003E;
&#x00A0;<br />#include&#x00A0;&#x003C;casacore/python/Converters/PycBasicData.h&#x003E;
&#x00A0;<br />#include&#x00A0;&#x003C;casacore/python/Converters/PycRecord.h&#x003E;
&#x00A0;<br />//&#x00A0;Include&#x00A0;file&#x00A0;for&#x00A0;boost&#x00A0;python.
&#x00A0;<br />#include&#x00A0;&#x003C;boost/python.hpp&#x003E;
&#x00A0;<br />
&#x00A0;<br />using&#x00A0;namespace&#x00A0;boost::python;
&#x00A0;<br />
&#x00A0;<br />namespace&#x00A0;casa&#x00A0;{&#x00A0;namespace&#x00A0;pyrap&#x00A0;{
&#x00A0;<br />&#x00A0;&#x00A0;void&#x00A0;wrap_xx()
&#x00A0;<br />&#x00A0;&#x00A0;{
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;//&#x00A0;Define&#x00A0;the&#x00A0;class;&#x00A0;"xx"&#x00A0;is&#x00A0;the&#x00A0;class&#x00A0;name&#x00A0;in&#x00A0;Python.
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;class_&#x003C;XX&#x003E;&#x00A0;("xx")
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;//&#x00A0;Define&#x00A0;the&#x00A0;constructor.
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;//&#x00A0;Multiple&#x00A0;constructors&#x00A0;can&#x00A0;be&#x00A0;defined.
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;//&#x00A0;They&#x00A0;have&#x00A0;to&#x00A0;have&#x00A0;different&#x00A0;number&#x00A0;of&#x00A0;arguments.
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;.def&#x00A0;(init&#x003C;&#x003E;())
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;//&#x00A0;Add&#x00A0;a&#x00A0;.def&#x00A0;line&#x00A0;for&#x00A0;each&#x00A0;function&#x00A0;to&#x00A0;be&#x00A0;wrapped.
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;//&#x00A0;An&#x00A0;arg&#x00A0;line&#x00A0;should&#x00A0;be&#x00A0;added&#x00A0;for&#x00A0;each&#x00A0;argument&#x00A0;giving
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;//&#x00A0;its&#x00A0;name&#x00A0;and&#x00A0;possibly&#x00A0;default&#x00A0;value.
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;.def&#x00A0;("func1",&#x00A0;&amp;XX::func1,
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;(boost::python::arg("arg1"),
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;boost::python::arg("arg2")=0))
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;;
&#x00A0;<br />&#x00A0;&#x00A0;}
&#x00A0;<br />}}
&#x00A0;<br />
&#x00A0;<br />BOOST_PYTHON_MODULE(_xx)
&#x00A0;<br />{
&#x00A0;<br />&#x00A0;&#x00A0;//&#x00A0;Register&#x00A0;the&#x00A0;conversion&#x00A0;functions.
&#x00A0;<br />&#x00A0;&#x00A0;casa::pyrap::register_convert_excp();
&#x00A0;<br />&#x00A0;&#x00A0;casa::pyrap::register_convert_basicdata();
&#x00A0;<br />&#x00A0;&#x00A0;casa::pyrap::register_convert_casa_record();
&#x00A0;<br />&#x00A0;&#x00A0;//&#x00A0;Initialize&#x00A0;the&#x00A0;wrapping.
&#x00A0;<br />&#x00A0;&#x00A0;casa::pyrap::wrap_xx();
                                                                     

                                                                     
&#x00A0;<br />}
</div>
</td></tr></table>
<!--l. 172--><p class="nopar" > Python requires for each package a file <span 
class="cmtt-10x-x-109">_</span><span 
class="cmtt-10x-x-109">_init</span><span 
class="cmtt-10x-x-109">_</span><span 
class="cmtt-10x-x-109">_.py</span>, so such an empty file
should be created as well.
<!--l. 176--><p class="noindent" >
   <h4 class="subsectionHead"><span class="titlemark">3.1   </span> <a 
 id="x1-60003.1"></a>More complicated wrappers</h4>
<!--l. 177--><p class="noindent" >Sometimes a C++ function cannot be wrapped directly, because the argument
order needs to be changed or because some extra Python checks are
necessary. In such a case the class needs to be implemented in Python
itself.
<br class="newline" />The C++ wrapped class name needs to get a different name, usually by
preceeding it with an underscore like:
                                                                     

                                                                     
   <table 
class="verbatim"><tr class="verbatim"><td 
class="verbatim"><div class="verbatim">
&#x00A0;&#x00A0;&#x00A0;&#x00A0;class_&#x003C;XX&#x003E;&#x00A0;("_xx")
</div>
</td></tr></table>
<!--l. 185--><p class="nopar" > The Python class should be derived from it and implement the constructor by
calling the constructor of _xx.
                                                                     

                                                                     
   <table 
class="verbatim"><tr class="verbatim"><td 
class="verbatim"><div class="verbatim">
class&#x00A0;xx(_xx):
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;def&#x00A0;__init__(self):
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;_xx.__init__(self)
</div>
</td></tr></table>
<!--l. 192--><p class="nopar" > Now <span 
class="cmtt-10x-x-109">xx </span>inherits all functions from <span 
class="cmtt-10x-x-109">_xx</span>. The required function can be written in
Python like
                                                                     

                                                                     
   <table 
class="verbatim"><tr class="verbatim"><td 
class="verbatim"><div class="verbatim">
&#x00A0;&#x00A0;&#x00A0;&#x00A0;def&#x00A0;func1&#x00A0;(self,&#x00A0;arg1,&#x00A0;arg2):
&#x00A0;<br />&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;return&#x00A0;self._func1&#x00A0;(arg2,&#x00A0;arg1);
</div>
</td></tr></table>
<!--l. 198--><p class="nopar" > Note that in the wrapper the function name also needs to be preceeded by an
underscore to make it different.
<!--l. 202--><p class="noindent" >
   <h4 class="subsectionHead"><span class="titlemark">3.2   </span> <a 
 id="x1-70003.2"></a>Combining multiple classes</h4>
<!--l. 203--><p class="noindent" >Sometimes one wants to combine multiple classes in a package. A example is
package <span 
class="cmtt-10x-x-109">pyrap</span><span 
class="cmtt-10x-x-109">_tables </span>which contains the classes <span 
class="cmtt-10x-x-109">table</span>, <span 
class="cmtt-10x-x-109">tablecolumn</span>,
<span 
class="cmtt-10x-x-109">tablerow</span>, <span 
class="cmtt-10x-x-109">tableiter</span>, and <span 
class="cmtt-10x-x-109">tableindex</span>. One is referred to the code of this
package to see how to do it.
<!--l. 210--><p class="noindent" >
   <h3 class="sectionHead"><span class="titlemark">4   </span> <a 
 id="x1-80004"></a>Python specifics</h3>
<!--l. 211--><p class="noindent" >Besides an array being in C-order, there are a few more Python specific
issues.
     <ul class="itemize1">
     <li class="itemize">Indexing starts at 0 (vs. 1 in glish).
     </li>
     <li class="itemize">The end value in a range like <span 
class="cmtt-10x-x-109">[10:20] </span>is exclusive (vs. inclusive in
     glish). Furthermore Python supports a step and reversed ranges.
     </li>
     <li class="itemize">Where useful, the function <span 
class="cmtt-10x-x-109">_</span><span 
class="cmtt-10x-x-109">_str</span><span 
class="cmtt-10x-x-109">_</span><span 
class="cmtt-10x-x-109">_ </span>should be added giving the name
     of the object. This function is used when printing an object.
     </li>
     <li class="itemize">Where useful, the functions <span 
class="cmtt-10x-x-109">_</span><span 
class="cmtt-10x-x-109">_len</span><span 
class="cmtt-10x-x-109">_</span><span 
class="cmtt-10x-x-109">_</span>, <span 
class="cmtt-10x-x-109">_</span><span 
class="cmtt-10x-x-109">_setitem</span><span 
class="cmtt-10x-x-109">_</span><span 
class="cmtt-10x-x-109">_(index, value)</span>,
     and  <span 
class="cmtt-10x-x-109">_</span><span 
class="cmtt-10x-x-109">_getitem</span><span 
class="cmtt-10x-x-109">_</span><span 
class="cmtt-10x-x-109">_(index) </span>should  be  added  to  make  it  possible
     that   a   user   indexes   an   object   directly   like   <span 
class="cmtt-10x-x-109">tabcol[i]  </span>or
     <span 
class="cmtt-10x-x-109">tabcol[start:stop:step]</span>.
                                                                     

                                                                     
     </li>
     <li class="itemize">When  these  functions  are  added,  Python  supports  iteration  in
     an  object.  Explicit  iteration  can  also  be  done  by  adding  the
     functions  <span 
class="cmtt-10x-x-109">_</span><span 
class="cmtt-10x-x-109">_iter</span><span 
class="cmtt-10x-x-109">_</span><span 
class="cmtt-10x-x-109">_ </span>and  <span 
class="cmtt-10x-x-109">next</span>.  At  the  end  <span 
class="cmtt-10x-x-109">next </span>should  raise  the
     Python <span 
class="cmtt-10x-x-109">StopIteration </span>exception (or throw <span 
class="cmtt-10x-x-109">casa::IterError </span>when
     implemented in C++) to stop the iteration.</li></ul>
    
</body></html>