Я не выяснил, как (или если) это можно сделать с помощью какого-то общего __setitem__
метода - моей первоначальной цели - но вот как определить пользовательский метод (с именем my_setitem()
ниже), которыйпохоже, что он может изменять значение индексированных элементов в массиве.
Это не позволит вам изменить значение подписываемого атрибута прокси-объекта напрямую подобноВы хотите, но это показывает способ их изменения.
Я думаю, что это будет работать в Python 3.7, так как я пытался избегать всего, что работало бы только в v3.8 с одним исключением , а именно эта новая функция , которая была добавлена в поддержку f-строки, очень удобна для отладки, но при необходимости ее относительно легко удалить / заменить.
from multiprocessing.managers import BaseManager, NamespaceProxy
import numpy as np
from functools import partial
print = partial(print, flush=True) # Change default.
class TestClass(object):
def __init__(self, a):
'''
Args:
a (np.ndarray): the array that needs to be changed
'''
print(f'TestClass.__init__ called, {a = }')
self.a = a
def my_setitem(self, name, index, value):
print(f'in TestClass.my_setitem()')
attr = getattr(self, name)
attr[index] = value
class TestProxy(NamespaceProxy):
# exposes the magic functions for TestProxy objects needed for setting their attributes
_exposed_ = ('__getattribute__', '__setattr__', '__delattr__', 'my_setitem')
def my_setitem(self, name, index, value):
print(f'in TestProxy.my_setitem()')
callmethod = object.__getattribute__(self, '_callmethod')
return callmethod('my_setitem', (name, index, value))
class MyManager(BaseManager):
pass
if __name__ == '__main__':
MyManager.register('Testclass', TestClass, TestProxy)
manager = MyManager()
manager.start()
arr = np.array([0,0,0,0])
print(f'calling manager.Testclass(arr)')
managed_obj = manager.Testclass(arr)
print(f'result: {managed_obj = }')
print()
# managed_obj.a[0] = 42 # The problem, doesn't work.
name = 'a'
index = 1
# index = slice(0, 2) # slices also work
print(f'executing managed_obj.my_setitem({name=}, {index=}, 42)')
managed_obj.my_setitem(name, index, 42)
print(f'result: {managed_obj.a = }') # -> result: managed_obj.a = array([ 0, 42, 0, 0])
Вот вывод, который он производит (работает с Py 3.8.0 в моей системе):
calling manager.Testclass(arr)
TestClass.__init__ called, a = array([0, 0, 0, 0])
result: managed_obj = <TestProxy object, typeid 'Testclass' at 0x4b3f520>
executing managed_obj.my_setitem(name='a', index=1, 42)
in TestProxy.my_setitem()
in TestClass.my_setitem()
result: managed_obj.a = array([ 0, 42, 0, 0])