59

I'd like to use namedtuples internally, but I want to preserve compatibility with users that feed me ordinary tuples.

from collections import namedtuple

tuple_pi = (1, 3.14, "pi")  #Normal tuple 

Record = namedtuple("Record", ["ID", "Value", "Name"])

named_e = Record(2, 2.79, "e")  #Named tuple

named_pi = Record(tuple_pi)  #Error
TypeError: __new__() missing 2 required positional arguments: 'Value' and 'Name'

tuple_pi.__class__ = Record
TypeError: __class__ assignment: only for heap types
0

1 Answer 1

86

You can use the *args call syntax:

named_pi = Record(*tuple_pi)

This passes in each element of the tuple_pi sequence as a separate argument.

You can also use the namedtuple._make() class method to turn any sequence into an instance:

named_pi = Record._make(tuple_pi)

Demo:

>>> from collections import namedtuple
>>> Record = namedtuple("Record", ["ID", "Value", "Name"])
>>> tuple_pi = (1, 3.14, "pi")
>>> Record(*tuple_pi)
Record(ID=1, Value=3.14, Name='pi')
>>> Record._make(tuple_pi)
Record(ID=1, Value=3.14, Name='pi')
6
  • 3
    Short and to-the-point. I cannot understand how did you manage to answer the question so quickly. Commented Jul 28, 2014 at 16:51
  • Nice. You can also use the keyword args syntax to hand over a dict: MyNamedTuple(**mydict). Of course the dict needs to contain the tuple fields as keys.
    – jurgispods
    Commented May 11, 2016 at 7:30
  • W.r.t. to memory consumption: I can get rid of tuplePi after converting it with namedPi = Record(*tuplePi) or with namedPi = Record._make(tuplePi), right?
    – thinwybk
    Commented Apr 13, 2018 at 14:37
  • @thinwybk: yes, the namedtuple instance now references the same values contained, so you don't need tuplePi anymore. Commented Apr 13, 2018 at 17:12
  • tuple.__new__(Record, tuple_pi) is what _make uses under the hood.
    – ofo
    Commented Jun 16, 2021 at 12:38

Not the answer you're looking for? Browse other questions tagged or ask your own question.