Is there a way to apply a function to all entries of a NamedTuple and get an object of the same type back?
The following code
from typing import NamedTuple
class MyNamedTuple(NamedTuple):
a: int
b: int
mnt = MyNamedTuple(1, 2)
fun = lambda x: x*x
m = map(fun, mnt)
will create a generator, but I would like to have another MyNamedTuple object instead. Is there a clean way to do this?
You can do it by examining the class' __annotations__ dictionary. One advantage — not being used in example below — is that the type of each field could also be checked and the function applied only if it made "sense" — e.g. only if it was numeric or was a string, etc.
from typing import NamedTuple
class MyNamedTuple(NamedTuple):
a: int
b: int
def apply(self, func):
"""Apply func to all fields of tuple and return new instance."""
values = map(func, (getattr(self, name) for name in type(self).__annotations__))
return type(self)(*values)
mnt = MyNamedTuple(1, 2)
m = mnt.apply(lambda x: x*x)
print(m) # -> MyNamedTuple(a=1, b=4)
You're almost there! You can pass the computed parameters back into the constructor for MyNamedTuple using the unpacking operator:
m = MyNamedTuple(*map(fun, mnt))
Then, if you do:
print(m.a)
print(m.b)
You will get:
1
4
as desired.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With