[Numpy-discussion] RecArray.tolist() suggestion
Francesc Alted
falted at pytables.org
Thu Jul 15 09:12:08 CDT 2004
A Dijous 15 Juliol 2004 17:21, Colin J. Williams va escriure:
> >What I propose is to be able to say:
> >>>>r["c1"][1]
> I would suggest going a step beyond this, so that one can have r.c1[1],
> see the script below.
Yeah. I've implemented something similar to access column elements for
pytables Table objects. However, the problem in this case is that there are
already attributes that "pollute" the column namespace, so that a column
named "size" collides with the size() method.
I came up with a solution by adding a new "cols" attribute to the Table
object that is an instance of a simple class named Cols with no attributes
that can pollute the namespace (except some starting by "__" or "_v_").
Then, it is just a matter of provide functionality to access the different
columns. In that case, when a reference of a column is made, another object
(instance of Column class) is returned. This Column object is basically an
accessor to column values with a __getitem__() and __setitem__() methods.
That might sound complicated, but it is not. I'm attaching part of the
relevant code below.
I personally like that solution in the context of pytables because it
extends the "natural naming" convention quite naturally. A similar approach
could be applied to RecArray objects as well, although numarray might (and
probably do) have other usage conventions.
> I have not explored the assignment of a value to r.c1.[1], but it seems
> to be achievable.
in the schema I've just proposed the next should be feasible:
value = r.cols.c1[1]
r.cols.c1[1] = value
--
Francesc Alted
-----------------------------------------------------------------
class Cols(object):
"""This is a container for columns in a table
It provides methods to get Column objects that gives access to the
data in the column.
Like with Group instances and AttributeSet instances, the natural
naming is used, i.e. you can access the columns on a table like if
they were normal Cols attributes.
Instance variables:
_v_table -- The parent table instance
_v_colnames -- List with all column names
Methods:
__getitem__(colname)
"""
def __init__(self, table):
"""Create the container to keep the column information.
table -- The parent table
"""
self.__dict__["_v_table"] = table
self.__dict__["_v_colnames"] = table.colnames
# Put the column in the local dictionary
for name in table.colnames:
self.__dict__[name] = Column(table, name)
def __len__(self):
return self._v_table.nrows
def __getitem__(self, name):
"""Get the column named "name" as an item."""
if not isinstance(name, types.StringType):
raise TypeError, \
"Only strings are allowed as keys of a Cols instance. You passed object: %s" % name
# If attribute does not exist, return None
if not name in self._v_colnames:
raise AttributeError, \
"Column name '%s' does not exist in table:\n'%s'" % (name, str(self._v_table))
return self.__dict__[name]
def __str__(self):
"""The string representation for this object."""
# The pathname
pathname = self._v_table._v_pathname
# Get this class name
classname = self.__class__.__name__
# The number of columns
ncols = len(self._v_colnames)
return "%s.cols (%s), %s columns" % (pathname, classname, ncols)
def __repr__(self):
"""A detailed string representation for this object."""
out = str(self) + "\n"
for name in self._v_colnames:
# Get this class name
classname = getattr(self, name).__class__.__name__
# The shape for this column
shape = self._v_table.colshapes[name]
# The type
tcol = self._v_table.coltypes[name]
if shape == 1:
shape = (1,)
out += " %s (%s%s, %s)" % (name, classname, shape, tcol) + "\n"
return out
class Column(object):
"""This is an accessor for the actual data in a table column
Instance variables:
table -- The parent table instance
name -- The name of the associated column
Methods:
__getitem__(key)
"""
def __init__(self, table, name):
"""Create the container to keep the column information.
table -- The parent table instance
name -- The name of the column that is associated with this object
"""
self.table = table
self.name = name
# Check whether an index exists or not
iname = "_i_"+table.name+"_"+name
self.index = None
if iname in table._v_parent._v_indices:
self.index = Index(where=self, name=iname,
expectedrows=table._v_expectedrows)
else:
self.index = None
def __getitem__(self, key):
"""Returns a column element or slice
It takes different actions depending on the type of the
"key" parameter:
If "key" is an integer, the corresponding element in the
column is returned as a NumArray/CharArray, or a scalar
object, depending on its shape. If "key" is a slice, the row
slice determined by this slice is returned as a NumArray or
CharArray object (whatever is appropriate).
"""
if isinstance(key, types.IntType):
if key < 0:
# To support negative values
key += self.table.nrows
(start, stop, step) = processRange(self.table.nrows, key, key+1, 1)
return self.table._read(start, stop, step, self.name, None)[0]
elif isinstance(key, types.SliceType):
(start, stop, step) = processRange(self.table.nrows, key.start,
key.stop, key.step)
return self.table._read(start, stop, step, self.name, None)
else:
raise TypeError, "'%s' key type is not valid in this context" % \
(key)
def __str__(self):
"""The string representation for this object."""
# The pathname
pathname = self.table._v_pathname
# Get this class name
classname = self.__class__.__name__
# The shape for this column
shape = self.table.colshapes[self.name]
if shape == 1:
shape = (1,)
# The type
tcol = self.table.coltypes[self.name]
return "%s.cols.%s (%s%s, %s)" % (pathname, self.name,
classname, shape, tcol)
def __repr__(self):
"""A detailed string representation for this object."""
return str(self)
More information about the Numpy-discussion
mailing list