Ana Nimbus
Ana Nimbus

Reputation: 735

How do you create a reusable or persistent map in Python 3?

I would like to be able to do, for example:

pmap = persistent_map(function, iterable(args))
foo = map(bar, pmap)
baz = map(bar, pmap) # right-hand side intentionally identical to that of the previous line.

The interpreter would know to reset pmap before using it to construct baz.

I know that I could store the result of pmap as a tuple, list, or other structure (which is what I have done in my present application), but I don't want to have do that because of the possibilities of 1) huge storage requirements (also consider copies) and 2) different results on reevalation, as when iterable is produced from a dynamic file.

If the equivalent of persistent_map exists, what is the corresponding built-in feature or standard library feature? Alternatively, is there a third-party (hopefully reliable and readily available) persistent_map equivalent? If only extant option is third-party, how might you create persistent_map using only built-in and, possibly, standard library features?

In response to @MartijnPieters comment, "that's what generators are for", are you saying that one solution would be something like

def persistent_map(function, iterable):
    from functools import partial
    return partial(map, function, iterable)
foo = map(bar, pmap())
baz = map(bar, pmap())
# A toy example:
pmap = persistent_map(hex, range(3))
foo = map(len , pmap())
baz = map(hash, pmap())
print(*zip(pmap(), foo, baz))
('0x0', 3, 982571147) ('0x1', 3, 982571146) ('0x2', 3, 982571145)

In response to @kmiya ("Bit too late...") and also, now that I think I understand better what @MartijnPieters meant by "that's what generators are for," I would do it this way:

class PersistentMap:
    def __init__(self, func, generator):
        self.func = func
        self.generator = generator
    def __iter__(self):
        return map(
            self.func,
            # THIS IS HOW "The interpreter [knows] to reset:"
            self.generator()
        )

# AN EXAMPLE GENERATOR.
# NOTE THAT STORING "ALL" THE GENERATED VALUES IS IMPOSSIBLE.
def tictoc():
    k = 0
    while True:
        yield k
        k = 1 - k

pmap = PersistentMap(hex, tictoc)
bar = map(len, pmap)
baz = map(hash, pmap)
limiter = range(3)
print(*zip(pmap, bar, baz, limiter))
# ('0x0', 3, 9079185981436209546, 0) ('0x1', 3, -8706547739535565546, 1) ('0x0', 3, 9079185981436209546, 2)
print(*zip(pmap, bar, baz, limiter))
# ('0x0', 3, 9079185981436209546, 0) ('0x1', 3, -8706547739535565546, 1) ('0x0', 3, 9079185981436209546, 2)

Upvotes: 1

Views: 510

Answers (1)

kmiya
kmiya

Reputation: 31

Bit too late, but I think this would be what the OP imagined to have:

class PersistentMap:
    def __init__(self, func, iterable):
        self.func = func
        self.iterable = iterable

    def __iter__(self):
        return map(self.func, self.iterable)

foo = PersistentMap(hex, range(3))
bar = map(len, foo)
baz = map(hash, foo)
print(*zip(foo, bar, baz))
# ('0x0', 3, -1640763679766387179) ('0x1', 3, -4170177621824264673) ('0x2', 3, 4695884286851555319)

Upvotes: 2

Related Questions