2
Support for arrays of nested records.
4
This module provides the `NestedRecArray` and `NestedRecord` classes,
5
which can be used to handle arrays of nested records in a way which is
6
compatible with ``numarray.records``.
8
Nested record arrays are made up by a sequence of nested records. A
9
nested record is made up of a set of non-nested and nested fields, each
10
of them having a different name. Non-nested fields have homogeneous
11
n-dimensional values (where n >= 1), while nested fields consist of a
12
set of fields (sub-fields), each of them with a different name.
13
Sub-fields can also be nested.
15
Several utility functions are provided for creating nested record
23
import numarray.strings
24
import numarray.records
26
from tables.attributeaccess import AttributeAccess
30
__docformat__ = 'reStructuredText'
31
"""The format of documentation strings in this module."""
35
def _isThereStructure(formats, descr, buffer):
37
Check if buffer structure is given. It must be given in order to
38
disambiguate possible ambiguities.
40
For an explanation of argument meanings see the `array()` function.
43
if not (formats or descr):
45
raise ValueError("""``formats`` or ``descr`` arguments """
46
"""must be given if ``buffer`` is ``None``""")
48
raise NotImplementedError("""unable to infer the buffer """
49
"""structure; it must be supplied with ``formats`` or """
50
"""``descr`` arguments""")
53
def _onlyOneSyntax(descr, formats, names):
55
Ensure that buffer structure is specified using either `descr` or
58
For an explanation of argument meanings see the `array()` function.
61
if descr and (formats or names):
62
raise ValueError("""only one syntax can be used to specify """
63
"""the buffer structure; please use either ``descr`` or """
64
"""``formats`` and ``names``""")
67
def _checkFormats(formats):
69
Check the format of the `formats` list.
71
For an explanation of argument meanings see the `array()` function.
74
# Formats description must be a list or a tuple
75
if not (isinstance(formats, list) or isinstance(formats, tuple)):
76
raise TypeError("""``formats`` argument must be a list or a tuple""")
78
# Formats elements must be strings or sequences
79
for item in nriterators.flattenFormats(formats, check=True):
81
raise TypeError("""elements of the ``formats`` list must """
82
"""be strings or sequences""")
85
def _checkNames(names):
87
Check the format of the `names` list.
89
For an explanation of argument meanings see the `array()` function.
92
# Names description must be a list or a tuple
93
if not (isinstance(names, list) or isinstance(names, tuple)):
94
raise TypeError("""``names`` argument must be a list""")
96
# Names elements must be strings or 2-tuples
97
for item in nriterators.flattenNames(names, check=True):
99
raise TypeError("""elements of the ``names`` list must be"""
100
""" strings or 2-tuples""")
102
# The names used in the names list should not contain the '/' string
103
for item in nriterators.getSubNames(names):
106
"""field names cannot contain the ``/`` character""")
108
# For every level of the names structure names must be unique
109
nriterators.checkNamesUniqueness(names)
112
def _checkDescr(descr):
114
Check the format of the `descr` list.
116
For an explanation of argument meanings see the `array()` function.
119
# descr must be a list
120
if not isinstance(descr, list):
121
raise TypeError("""the descr argument must be a list!""")
123
# descr must be a list of 2-tuples
124
for item in nriterators.flattenDescr(descr, check=True):
127
"""elements of the `descr` list must be 2-tuples!""")
130
def _checkFieldsInDescr(descr):
132
Check that field names do not contain the ``/`` character.
134
The checking is done on the most deeply nested field names. For an
135
explanation of argument meanings see the `array()` function.
138
names = [item for item in nriterators.getNamesFromDescr(descr)]
142
def makeDescr(formats, names=None):
144
Create a ``descr`` list for the array.
146
If no `names` are passed fields are automatically named as ``c1``,
150
return [item for item in nriterators.getDescr(names, formats)]
153
def makeFormats(descr):
154
"""Create a ``formats`` list for the array."""
156
return [item for item in nriterators.getFormatsFromDescr(descr)]
159
def makeNames(descr):
160
"""Create a ``names`` list for the array."""
162
return [item for item in nriterators.getNamesFromDescr(descr)]
165
def _checkBufferStructure(structure, buffer):
167
Check the `buffer` structure using the given `structure`.
169
The checking is done after flattening both the `structure` and the
170
`buffer`. `structure` is the descr list that describes the buffer
171
structure. buffer` has its usual meaning in this module.
175
for item in nriterators.zipBufferDescr(row, structure):
176
if not (isinstance(item, tuple) and len(item) == 2):
177
raise ValueError("""row structure doesn't match that """
178
"""provided by the format specification""")
179
if not isinstance(item[1], str):
180
raise TypeError("""field descriptors must be strings""")
183
def _matchFormats(seq1, seq2):
184
"""Check if two flat formats lists are equivalent."""
186
# Lists must have the same length
187
if len(seq1) != len(seq2):
188
raise ValueError("""buffer structure doesn't match that """
189
"""provided by the format specification""")
191
# Elements in the same position must describe the same format
192
for (f1, f2) in zip(seq1, seq2):
193
ra1 = numarray.records.array(buffer=None, formats = [f1])
194
ra2 = numarray.records.array(buffer=None, formats = [f2])
195
if ra1._formats != ra2._formats:
196
raise ValueError("""buffer formats don't match those """
197
"""provided by the format specification""")
200
def _narrowRecArray(recarray, startField, newFieldNames):
202
Take a set of contiguous columns from a ``RecArray``.
204
This function creates and returns a new ``RecArray`` by taking a
205
number of contiguous columns from `recarray`, starting by field
206
`startField`. The new columns take their names from the
207
`newFieldNames` list, which also determines the number of fields to
208
take. The resulting array shares its data with `recarray`.
211
iStartField = recarray._names.index(startField)
212
iEndField = iStartField + len(newFieldNames)
213
byteOffset = recarray.field(iStartField)._byteoffset
214
return numarray.records.RecArray(
215
recarray._data, recarray._formats[iStartField:iEndField],
216
shape=recarray._shape, names=newFieldNames, byteoffset=byteOffset,
217
bytestride=recarray._bytestride, byteorder=recarray._byteorder,
218
aligned=recarray.isaligned())
221
def array(buffer=None, formats=None, shape=0, names=None,
222
byteorder=sys.byteorder, aligned=0, descr=None):
224
Create a new instance of a `NestedRecArray`.
226
This function can be used to build a new array of nested records.
227
The new array is returned as a result.
229
The function works much like ``numarray.records.array()``, with some
232
1. In addition to flat buffers and regular sequences of non-nested
233
elements, the `buffer` argument can take regular sequences where
234
each element has a structure nested to an arbitrary depth. Of
235
course, all elements in a non-flat buffer must have the same
238
2. The `formats` argument only supports sequences of strings and
239
other sequences. Each string defines the shape and type of a
240
non-nested field. Each sequence contains the formats of the
241
sub-fields of a nested field.
243
The structure of this argument must match that of the elements in
244
`buffer`. This argument may have a recursive structure.
246
3. The `names` argument only supports lists of strings and 2-tuples.
247
Each string defines the name of a non-nested field. Each 2-tuple
248
contains the name of a nested field and a list describing the
249
names of its sub-fields.
251
The structure of this argument must match that of the elements in
252
`buffer`. This argument may have a recursive structure.
254
The `descr` argument is a new-style description of the structure of
255
the `buffer`. It is intended to replace the `formats` and `names`
256
arguments, so they can not be used at the same time [#descr]_.
258
The `descr` argument is a list of 2-tuples, each of them describing
259
a field. The first value in a tuple is the *name* of the field,
260
while the second one is a description of its *structure*. If the
261
second value is a string, it defines the format (shape and type) of
262
a non-nested field. Else, it is a list of 2-tuples describing the
263
sub-fields of a nested field.
265
If `descr` is ``None`` (or omitted), the whole structure of the
266
array is tried to be inferred from that of the `buffer`, and
267
automatic names (``c1``, ``c2`` etc. on each nested field) are
268
assigned to all fields.
270
The `descr` argument may have a recursive structure.
272
Please note that names used in `names` or `descr` should *not*
273
contain the string ``'/'``, since it is used as the field/sub-field
274
separator by `NestedRecArray.asRecArray()`. If the separator is
275
found in a name, a ``ValueError`` is raised.
277
.. [#descr] The syntax of `descr` is based on that of the
278
``__array_descr__`` attribute in the proposed standard
279
`N-dimensional array interface`__.
281
__ http://numeric.scipy.org/array_interface.html
284
When to use `descr` or `formats`
285
================================
287
Since `descr` requires both the name and structure of fields to
288
always be specified, the `formats` argument comes more handy when
289
one does not want to explicitly specify names. However it is not
290
allowed to use the `names` argument without the `formats` one. This
291
is due to the fact that automatic inferrence of the `buffer`
292
structure is not implemented. When fully specifying names and
293
structure, the `descr` argument is preferred over `formats` and
294
`names` for the sake of code legibility and conciseness.
300
The following examples will help to clarify the words above. In
301
them, an array of two elements is created. Each element has three
302
fields: a 64-bit integer (``id``), a bi-dimensional 32-bit floating
303
point (``pos``) and a nested field (``info``); the nested field has
304
two sub-fields: a two-character string (``name``) and a 64-bit
310
In this example the array is created by specifying both its contents
311
and its structure, so the structure of the used arguments must be
314
This is how the array would be created in the old-style way,
315
i.e. using the `formats` and `names` arguments:
318
... [(1, (0.5, 1.0), ('a1', 1j)), (2, (0, 0), ('a2', 1+.1j))],
319
... names=['id', 'pos', ('info', ['name', 'value'])],
320
... formats=['Int64', '(2,)Float32', ['a2', 'Complex64']])
322
And this is how the array would be created in the new-style way,
323
i.e. using the `descr` argument:
326
... [(1, (0.5, 1.0), ('a1', 1j)), (2, (0, 0), ('a2', 1+.1j))],
327
... descr=[('id', 'Int64'), ('pos', '(2,)Float32'),
328
... ('info', [('name', 'a2'), ('value', 'Complex64')])])
330
Note how `formats` and `descr` mimic the structure of each the
331
elements in `buffer`.
336
Now the array is created from a flat string representing the data in
337
memory. Names will be automatically assigned. For that to work,
338
the resulting array shape and record format must be fully specified.
340
>>> datastring = binary_representation_of_data
342
... datastring, shape=2,
343
... formats=['Int64', '(2,)Float32', ['a2', 'Complex64']])
345
Byte ordering and alignment is assumed to be that of the host
346
machine, since it has not been explicitly stated via the `byteorder`
347
and `aligned` arguments.
350
# Check if a buffer structure is given. It must be given in order to
351
# disambiguate possible ambiguities
352
_isThereStructure(formats, descr, buffer)
354
# Check if buffer structure is specified using descr OR formats (and,
356
_onlyOneSyntax(descr, formats, names)
358
# This is to keep compatibility with numarray.records.array function
359
if isinstance(formats, str):
360
formats = formats.split(',')
361
if isinstance(names, str):
362
names = names.split(',')
364
# Check the descr format
365
# Check for '/' in descr
367
descr = makeDescr(formats, names)
369
_checkFieldsInDescr(descr)
371
# Check the formats format
373
formats = makeFormats(descr)
374
_checkFormats(formats)
376
# Check the names format
378
names = makeNames(descr)
381
# Flatten the structure descriptors
382
flatFormats = [item for item in nriterators.flattenFormats(formats)]
383
flatNames = [item for item in nriterators.flattenNames(names)]
385
# Check the buffer structure (order matters!)
386
if isinstance(buffer, NestedRecArray):
387
_matchFormats( flatFormats, buffer._flatArray._formats)
388
elif isinstance(buffer, numarray.records.RecArray):
389
_matchFormats( flatFormats, buffer._formats)
390
elif (isinstance(buffer, types.ListType) or
391
isinstance(buffer, types.TupleType)):
392
if (isinstance(buffer[0], numarray.NumArray) or
393
isinstance(buffer[0], numarray.strings.CharArray)):
394
return fromarrays(buffer, formats=formats,
395
shape=shape, names=names,
396
byteorder=byteorder, aligned=aligned)
398
_checkBufferStructure( descr, buffer)
400
# If buffer is a RecArray then we have almost done with the creation
401
if isinstance(buffer, numarray.records.RecArray):
402
if isinstance(buffer, NestedRecArray):
403
flatBuffer = buffer.asRecArray()
405
flatBuffer = buffer.copy()
406
newFlatArray = _narrowRecArray(flatBuffer, flatBuffer._names[0],
408
return NestedRecArray(newFlatArray, descr)
410
# Flatten the buffer (if any)
414
# Buffer is a list of sequences. Every sublist represents a row
417
[tuple([v for (v, f) in nriterators.zipBufferDescr(row, descr)])
420
# Create a flat recarray
421
flatArray = numarray.records.array(
422
flatBuffer, flatFormats, shape, flatNames, byteorder, aligned)
424
# Create the nested recarray
425
return NestedRecArray(flatArray, descr)
428
def _checkArrayList(arrayList):
430
Check the type of the arraylist argument of fromarrays.
432
For an explanation of argument meanings see the `array()` function.
435
# The argument must be a list or a tuple
436
if not (isinstance(arrayList, list) or isinstance(arrayList, tuple)):
437
raise TypeError("""``arrayList`` argument must be a list or a tuple""")
439
def fromarrays(arrayList, formats=None, names=None, shape=0,
440
byteorder=sys.byteorder, aligned=0, descr=None):
442
Create a new instance of a `NestedRecArray` from field arrays.
444
This function can be used to build a new array of nested records
445
from a list of arrays, one for each field. The new array is
446
returned as a result.
448
The function works much like ``numarray.records.fromarrays()``, but
449
`arrayList` may also contain nested fields, i.e. sequences of other
450
arrays (nested or not). All non-nested arrays appearing in
451
`arrayList` must have the same length.
453
The rest of arguments work as explained in `array()`.
459
Let us build the sample array used in the examples of `array()`. In
462
>>> nra = fromarrays(
463
... [[1, 2], [(0.5, 1.0), (0, 0)], [['a1', 'a2'], [1j, 1+.1j]]],
464
... names=['id', 'pos', ('info', ['name', 'value'])],
465
... formats=['Int64', '(2,)Float32', ['a2', 'Complex64']])
469
>>> nra = fromarrays(
470
... [[1, 2], [(0.5, 1.0), (0, 0)], [['a1', 'a2'], [1j, 1+.1j]]],
471
... descr=[('id', 'Int64'), ('pos', '(2,)Float32'),
472
... ('info', [('name', 'a2'), ('value', 'Complex64')])])
474
Note how `formats` and `descr` mimic the structure of the whole
478
_checkArrayList(arrayList)
480
# Check if a buffer structure is given. It must be given in order to
481
# disambiguate possible ambiguities
482
_isThereStructure(formats, descr, arrayList)
484
# Check if buffer structure is specified using descr OR formats (and,
486
_onlyOneSyntax(descr, formats, names)
488
# This is to keep compatibility with numarray.records.array function
489
if isinstance(formats, str):
490
formats = formats.split(',')
491
if isinstance(names, str):
492
names = names.split(',')
494
# Check the descr format
495
# Check for '/' in descr
497
descr = makeDescr(formats, names)
499
_checkFieldsInDescr(descr)
501
# Check the formats format
503
formats = makeFormats(descr)
504
_checkFormats(formats)
506
# Check the names format
508
names = makeNames(descr)
511
# Flatten the structure descriptors
512
flatFormats = [item for item in nriterators.flattenFormats(formats)]
513
flatNames = [item for item in nriterators.flattenNames(names)]
515
# Create a regular recarray from the arrays list
517
nriterators.flattenArraysList(arrayList, descr, flatArrayList)
518
ra = numarray.records.fromarrays(flatArrayList, formats=flatFormats,
519
names=flatNames, shape=shape, byteorder=byteorder, aligned=aligned)
521
# Create the nested recarray
522
nra = NestedRecArray(ra, descr)
527
class NestedRecArray(numarray.records.RecArray):
530
Array of nested records.
532
This is a generalization of the ``numarray.records.RecArray`` class.
533
It supports nested fields and records via the `NestedRecord` class.
535
This class is compatible with ``RecArray``. However, part of its
536
behaviour has been extended to support nested fields:
538
1. Getting a single item from an array will return a `NestedRecord`,
539
a special kind of ``Record`` with support for nested structures.
541
2. Getting a range of items will return another `NestedRecArray`
542
instead of an ordinary ``RecArray``.
544
3. Getting a whole field may return a `NestedRecArray` instead of a
545
``NumArray`` or ``CharArray``, if the field is nested.
547
Fields and sub-fields can be accessed using both the `field()`
548
method and the ``fields`` interface, which allows accessing fields
549
as Python attributes: ``nrec = nrarr.fields.f1.fields.subf1[4]``.
550
The `field()` method supports the ``'/'`` separator to access
553
Nested record arrays can be converted to ordinary record arrays by
554
using the `asRecArray()` method.
556
Finally, the constructor of this class is not intended to be used
557
directly by users. Instead, use one of the creation functions
558
(`array()`, `fromarrays()` or the others).
561
def __init__(self, recarray, descr):
562
super(NestedRecArray, self).__init__(
563
recarray._data, recarray._formats, shape=recarray._shape,
564
names=recarray._names, byteoffset=recarray._byteoffset,
565
bytestride=recarray._bytestride,
566
byteorder=recarray._byteorder, aligned=recarray.isaligned())
567
# ``_strides`` is not properly copied from the original array,
568
# so, the copy must be made by hand. :[
569
self._strides = recarray._strides
571
self._flatArray = recarray
574
self.fields = AttributeAccess(self, 'field')
576
Provides attribute access to fields.
578
For instance, accessing ``recarray.fields.x`` is equivalent to
579
``recarray.field('x')``, and ``recarray.fields.x.fields.y`` is
580
equivalent to ``recarray.field('x/y')``. This functionality is
581
mainly intended for interactive usage from the Python console.
586
"""Return a string representation of the nested record array."""
589
psData['psClassName'] = self.__class__.__name__
590
psData['psElems'] = ',\n'.join([str(elem) for elem in self])
600
Return the canonical string representation of the nested record
605
rsData['rsElems'] = '[%s]' % ',\n'.join([str(elem) for elem in self])
606
rsData['rsDescr'] = str(self.descr)
607
rsData['rsShape'] = str(self.shape[0])
613
shape=%(rsShape)s)''' % rsData
616
def __getitem__(self, key):
617
if not isinstance(key, slice):
618
# The `key` must be a single index.
619
# Let `self._getitem()` do the job.
620
return super(NestedRecArray, self).__getitem__(key)
622
# The `key` is a slice.
623
# Delegate selection to flat array and build a nested one from that.
624
return NestedRecArray(self._flatArray[key], self.descr)
627
def _getitem(self, offset):
628
flatArray = self._flatArray
629
row = (offset - flatArray._byteoffset) / flatArray._strides[0]
630
return NestedRecord(self, row)
633
def __setitem__(self, key, value):
634
_RecArray = numarray.records.RecArray # Should't it be NestedRecArray?
635
if isinstance(key, slice) and not isinstance(value, _RecArray):
636
# Conversion of the value to an array will need a little help
637
# until structure inference is supported.
639
print 'Description', self.descr
640
value = array(value, descr=self.descr)
641
#super(NestedRecArray, self).__setitem__(key, value)
642
# Call the setitem method with the flatArray mate instead.
643
# It's extremely important doing this because the shape can
644
# be temporarily modified during the assign process, and self
645
# and self._flatArray may end having different shapes, which
646
# gives problems (specially with numarray > 1.1.1)
647
# F. Altet 2005-06-09
648
self._flatArray.__setitem__(key, value)
651
# It seems like this method is never called, because __setitem__ calls
652
# the flatArray (RecArray object) __setitem__
653
# F. Altet 2005-06-09
654
# def _setitem(self, offset, value):
655
# row = (offset - self._byteoffset) / self._strides[0]
656
# for i in range(0, self._nfields):
657
# self._flatArray.field(self._names[i])[row] = \
658
# value.field(self._names[i])
661
def __add__(self, other):
662
"""Add two NestedRecArray objects in a row wise manner."""
664
if isinstance(other, NestedRecArray):
665
return NestedRecArray(self._flatArray + other._flatArray,
668
# Assume other is a RecArray
669
return NestedRecArray(self._flatArray + other, self.descr)
672
def field(self, fieldName):
674
Get field data as an array.
676
`fieldName` can be the name or the index of a field in the
677
record array. If it is not nested, a ``NumArray`` or
678
``CharArray`` object representing the values in that field is
679
returned. Else, a `NestedRecArray` object is returned.
681
`fieldName` can be used to provide the name of sub-fields. In
682
that case, it will consist of several field name components
683
separated by the string ``'/'``. For instance, if there is a
684
nested field named ``x`` with a sub-field named ``y``, the last
685
one can be accesed by using ``'x/y'`` as the value of
689
# fieldName can be an integer, get the corresponding name
690
if isinstance(fieldName, int):
691
fieldName = self.descr[fieldName][0]
693
# The descr list of the field whose content is being extracted
695
item for item in nriterators.getFieldDescr(fieldName, self.descr)]
697
raise ValueError("there is no field named ``%s``" % (fieldName,))
698
fieldDescr = fieldDescr[0][1]
700
# Case 1) non nested fields (bottom level)
701
if isinstance(fieldDescr, str):
702
# The field content is returned as numarray or chararray
703
return self._flatArray.field(fieldName)
705
# Case 2) nested fields (both top and intermediate levels)
706
# We need fully qualified names to access the flat array fields
708
name for name in nriterators.getNamesFromDescr(fieldDescr)]
710
name for name in nriterators.flattenNames(fieldNames)]
712
# This is the flattened name of the original first bottom field.
713
startField = '%s/%s' % (fieldName, flatNames[0])
714
# Get the requested fields from the flat array and build a nested one.
715
newFlatArray = _narrowRecArray(self._flatArray, startField, flatNames)
716
return NestedRecArray(newFlatArray, fieldDescr)
719
def asRecArray(self, copy=True):
721
Convert a nested array to a non-nested equivalent array.
723
This function creates a new vanilla ``RecArray`` instance
724
equivalent to this one by *flattening* its fields. Only
725
bottom-level fields are included in the array. Sub-fields are
726
named by prepending the names of their parent fields up to the
727
top-level fields, using ``'/'`` as a separator.
729
By default the data area of the array is copied into the new one,
730
but a pointer to the data area can be returned if the copy
731
argument is set to False.
736
Let us take the following nested array:
738
>>> nra = array([(1, (0, 0), ('a1', 1j)), (2, (0, 0), ('a2', 2j))],
739
... names=['id', 'pos', ('info', ['name', 'value'])],
740
... formats=['Int64', '(2,)Float32', ['a2', 'Complex64']])
742
Calling ``nra.asRecArray()`` would return the same array as
745
>>> ra = numarray.records.array(
746
... [(1, (0, 0), 'a1', 1j), (2, (0, 0), 'a2', 2j)],
747
... names=['id', 'pos', 'info/name', 'info/value'],
748
... formats=['Int64', '(2,)Float32', 'a2', 'Complex64'])
750
Please note that the shape of multi-dimensional fields is kept.
754
return self._flatArray.copy()
756
return self._flatArray
760
return NestedRecArray(self._flatArray.copy(), self.descr)
764
class NestedRecord(numarray.records.Record):
769
This is a generalization of the ``numarray.records.Record`` class to
770
support nested fields. It represents a record in a `NestedRecArray`
771
or an isolated record. In the second case, its names are
772
automatically set to ``c1``, ``c2`` etc. on each nested field.
774
This class is compatible with ``Record``. However, getting a field
775
may return a `NestedRecord` instead of a Python scalar, ``NumArray``
776
or ``CharArray``, if the field is nested.
778
Fields and sub-fields can be accessed using both the `field()`
779
method and the ``fields`` interface, which allows accessing fields
780
as Python attributes: ``nfld = nrec.fields.f1.fields.subf1[4]``.
781
The `field()` method supports the ``'/'`` separator to access
784
Nested records can be converted to ordinary records by using the
788
def __init__(self, input, row=0):
789
numarray.records.Record.__init__(self, input._flatArray, row)
792
self.fields = AttributeAccess(self, 'field')
794
Provides attribute access to fields.
796
For instance, accessing ``record.fields.x`` is equivalent to
797
``record.field('x')``, and ``record.fields.x.fields.y`` is
798
equivalent to ``record.field('x/y')``. This functionality is
799
mainly intended for interactive usage from the Python console.
804
"""Return a string representation of the nested record."""
806
# This is only defined to avoid falling back to ``Record.__str__()``.
811
"""Return the canonical string representation of the nested record."""
816
fieldNames = [fieldName for (fieldName, fieldFormat) in nra.descr]
819
for fieldName in fieldNames:
820
rsFieldValue = repr(nra.field(fieldName)[row])
821
field_rsValues.append(rsFieldValue)
822
rsFieldValues = '(%s)' % ', '.join(field_rsValues)
826
def field(self, fieldName):
830
If the named field (`fieldName`, a string) is not nested, a
831
Python scalar, ``NumArray`` or ``CharArray`` object with the
832
value of that field is returned. Else, a `NestedRecord` object
835
`fieldName` can be used to provide the name of sub-fields. In
836
that case, it will consist of several field name components
837
separated by the string ``'/'``. For instance, if there is a
838
nested field named ``x`` with a sub-field named ``y``, the last
839
one can be accesed by using ``'x/y'`` as the value of
842
return self.array.field(fieldName)[self.row]
847
Convert a nested record to a non-nested equivalent record.
849
This function creates a new vanilla ``Record`` instance
850
equivalent to this one by *flattening* its fields. Only
851
bottom-level fields are included in the array.
853
The *whole array* to which the record belongs is copied. If you
854
want to repeatedly access nested records as flat records you
855
should consider converting the whole nested array into a flat
856
one and access its records normally.
861
Let us take the following nested record:
863
>>> nr = NestedRecord([1, (0, 0), ('a1', 1j)])
865
Calling ``nr.asRecord()`` would return the same record as
868
>>> r = numarray.records.Record([1, (0, 0), 'a1', 1j])
870
Please note that the shape of multi-dimensional fields is kept.
872
return self.array.asRecArray()[self.row]
876
"""Get the number of fields in this record."""
877
return len(self.array.descr)
880
def __getitem__(self, fieldName):
881
"""Get the value of the field `fieldName`."""
882
return self.field(fieldName)
885
def __setitem__(self, fieldName, value):
886
"""Set the `value` of the field `fieldName`."""
887
self.setfield(fieldName, value)
892
Make a copy of this record.
894
Only one row of the nested recarray is copied. This is useful in
895
some corner cases, for instance
897
(nra[0], nra[-1]) = (nra[-1], nra[0])
901
(nra[0], nra[-1]) = (nra[-1].copy(), nra[0].copy())
905
No data are shared between the copy and the source.
907
nra = NestedRecArray(self.array[self.row:self.row + 1].asRecArray(),
909
return NestedRecord(nra, 0)
915
## py-indent-offset: 4