0

I am writing this question, because it does not seem like what I am experiencing should be the desired behavior:

The following code is pretty much lifted from the 3.9.16 documentation on multiprocessing.Manager

from multiprocessing import Process, Manager

def f(d, l):
    d[1] = '1'
    d['2'] = 2
    d[0.25] = None
    l.reverse()

def multi_foo():
    with Manager() as manager:
        d = manager.dict()
        l = manager.list(range(10))
        jobs = []
        for _ in range(1):
            p = Process(target=f, args=(d, l))
            jobs.append(p)
            p.start()
        for _j in jobs:
            _j.join()

        print(f"{d=}")
        print(d)
        print(f"{l=}")
        print(l)
        ell = l[:]
        print(f"{ell=}")

if __name__ == '__main__':
    multi_foo()

This is the output that running the above code yields:

d=<DictProxy object, typeid 'dict' at 0x100cf2550>
{1: '1', '2': 2, 0.25: None}
l=<ListProxy object, typeid 'list' at 0x100f82790>
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
ell=[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

It seems to me that the 3rd line should be more like the 5th line. So it does not feel like the f-string outputs on lines 1 and 3 should be expected.

I am looking for an explanation for why I should expect what I get in the 1st and 3rd line of the output.

E_net4
  • 27,810
  • 13
  • 101
  • 139
tipanverella
  • 3,477
  • 3
  • 25
  • 41

1 Answers1

2

f'{...=}' uses the value's __repr__ method, not its __str__ method, to print the value. From the documentation:

By default, the '=' causes the repr() of the expression to be provided, unless there is a format specified.

In the case of DictProxy and ListProxy objects, __str__ and __repr__ return very different strings. For list objects, list.__str__ is not even defined, and so object.__str__ is used (which just calls an object's __repr__ method).

Consider:

class A:
    def __str__(self):
        return "string"
    def __repr__(self):
        return "repr"

a = A()
print(a)  # outputs string, as print calls str() on each argument
assert f'{a}' == "string"  # uses a.__str__()
assert f'{a=}' == "a=repr"  # uses a.__repr__()
assert f'{a=!s}' == "a=string"  # !s forces use of __str__
chepner
  • 497,756
  • 71
  • 530
  • 681
  • That's a good enough answer for me. We are saying that this is the desired behavior. I can accept that. – tipanverella Mar 16 '23 at 02:24
  • One more question, is this copying approach, `ell = l[:]`, the best course of action in this case? – tipanverella Mar 16 '23 at 02:26
  • What case is that? A `ListProxy` is a way to share a single list between processes. Are you just trying to extract a real `list` object? This is really an entirely separate question. – chepner Mar 16 '23 at 11:44