Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map a function to all a typing.NamedTuple fields and get one back?

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?

like image 915
fuenfundachtzig Avatar asked Oct 30 '25 03:10

fuenfundachtzig


2 Answers

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)

like image 189
martineau Avatar answered Nov 01 '25 18:11

martineau


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.

like image 28
BrokenBenchmark Avatar answered Nov 01 '25 17:11

BrokenBenchmark



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!