A Khalifa
A Khalifa

Reputation: 21

How to mutate a namedtuple?

I have a list of namedtuples. I want to mutate some of the values inside, however a tuple of course is immutable. I wonder if I can replace the entire tuple, but first I need to understand its struture, which I haven't found in the documentation.

def _createRowClass(self):
    self.Row = namedtuple('Row', [str(c) for c in self._columns])
#_columns is a dict.

def addRow(self, *args, **kwargs):
    self._rows.append(self.Row(*args, **kwargs))

An example element of _rows:

Out[40]: Row(rlnCoordinateX='1951.892292', rlnCoordinateY='1482.277896', rlnHelicalTubeID='6', rlnAngleTiltPrior='90.000000', rlnAnglePsiPrior='-110.29072', rlnHelicalTrackLength='1264.598540', rlnAnglePsiFlipRatio='0.500000', rlnImageName='000243@Extract/job011/Movies/Microtubules_02563.mrcs', rlnMicrographName='MotionCorr/job003/Movies/Microtubules_02563.mrc', rlnMagnification='10000.000000', rlnDetectorPixelSize='5.480000', rlnCtfMaxResolution='5.830000', rlnCtfFigureOfMerit='0.124704', rlnVoltage='300.000000', rlnDefocusU='7457.819824', rlnDefocusV='6964.129883', rlnDefocusAngle='33.520000', rlnSphericalAberration='2.700000', rlnCtfBfactor='0.000000', rlnCtfScalefactor='1.000000', rlnPhaseShift='0.000000', rlnAmplitudeContrast='0.100000', rlnOriginX='0.000000', rlnOriginY='0.000000')

When I index the namedtuple I get the value, but not the key, so what is this exactly: rlnAmplitudeContrast='0.100000'?

I'm thinking maybe recreate this namedtuple with the changes I want, like replace rlnVoltage to 200,000000 instead of 300,000000 then replace this namedtuple in the list with the new mutated one? How can I do that?

Any other suggestions and ideas are appreciated.

Upvotes: 2

Views: 1443

Answers (1)

juanpa.arrivillaga
juanpa.arrivillaga

Reputation: 95948

Objects of a type created by namedtuple have a ._replace method to conveniently create a new tuple with updated fields (not mutate):

>>> from collections import namedtuple
>>> Record = namedtuple('Record', 'name age id')
>>> r = Record('Juan', '30', 1)
>>> r
Record(name='Juan', age='30', id=1)
>>> r._replace(name='Pablo')
Record(name='Pablo', age='30', id=1)
>>> r._replace(name='Jon', age='31')
Record(name='Jon', age='31', id=1)

Note, namedtuple objects break the convention of single-underscores for non-public parts of the API, _replace is a part of the public API in this case.

Upvotes: 2

Related Questions