Я пытаюсь сослаться на фрагмент «глобального» массива с помощью атрибута объекта. Вот то, на что, я думаю, будет похожа структура класса, и это вариант использования.
import numpy
class X:
def __init__(self, parent):
self.parent = parent
self.pid = [0, 1, 2]
def __getattr__(self, name):
if name == 'values':
return self.parent.P[self.pid]
else:
raise AttributeError
class Node:
def __init__(self):
self.P = numpy.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
self._values = X(self)
def __getattr__(self, name):
if name == 'x':
return self._values.values
else:
raise AttributeError
Вот пример использования:
>>> n = Node()
>>> print n.P
[ 1 2 3 4 5 6 7 8 9 10]
>>> print n.x
[1 2 3]
>>> print n.x[1:3]
[2 3]
Что отлично работает, теперь я хотел бы присвоить значения n.P
через атрибут n.x
,
>>> n.x = numpy.array([11, 12, 13])
чтобы получить,
>>> print n.P
[ 11 12 13 4 5 6 7 8 9 10]
Или назначить значения срезами,
>>> n.x[1:3] = numpy.array([77, 88])
чтобы получить,
>>> print n.P
[ 11 77 88 4 5 6 7 8 9 10]
Но ради жизни я изо всех сил стараюсь, чтобы это задание работало. Я думал, что будет легко использовать __setattr__
и __setitem__
, но целый день я все еще не справился с этим.
В конечном итоге, n.x
будет возвращен в виде многомерного массива, в котором класс X
изменится по возвращении, но будет сохранен в n.P
, который является вектором. Я удалил это, чтобы упростить проблему.
Я бы хотел помочь с этим. Кто-нибудь делал это раньше? Или подсказать как это сделать?
Заранее спасибо за помощь.
РЕШЕНИЕ
Так что после многих дней спотыкания я нашел решение. Я подозреваю, что это может быть упрощено и улучшено. Решение состоит в том, чтобы создать объект X в вашем объекте Node. Когда он извлекается, он возвращает временный объект numpy (значения) со знанием его родительского узла и pids. Функция setslice _ определяется в этом обновлении глобального массива P с новыми значениями. Если объект X назначен, он не возвращает объект Values, а непосредственно устанавливает глобальные значения P.
Две точки, которые могут быть недействительными: 1. Объекты Node и X должны были быть подклассом object ; 2. если вы устанавливаете массив с более высокой размерностью, вам нужно вместо этого использовать __setitem__
, который не будет работать с массивами или списками 1D.
Как я уже сказал, я подозреваю, что этот код можно улучшить, так как я не уверен, что полностью его понимаю. Я рад принимать улучшения и предложения.
Спасибо за вашу помощь, особенно Баго.
Вот мой окончательный код.
import numpy
class Values(numpy.ndarray):
def __new__(cls, input_array, node, pids):
obj = numpy.asarray(input_array).view(cls)
obj.node = node
obj.pids = pids
return obj
def __setslice__(self, i, j, values):
self.node._set_values(self.pids[i:j], values)
class X(object):
def __get__(self, instance, owner):
p = instance.P[instance.pids]
return Values(p, instance, instance.pids)
def __set__(self, instance, values):
instance.P[instance.pids] = values
class Node(object):
x = X()
def __init__(self, pids=[0, 1, 2]):
self.P = numpy.arange(11)
self.pids = pids
def _set_values(self, pids, values):
self.P[pids] = values
node = Node(pids=[4, 5, 6, 7])
print '\nInitial State:'
print 'P =', node.P
print 'x =', node.x
print 'x[1:3] =', node.x[1:3]
print '\nSetting node.x = [44, 55, 66, 77]:'
node.x = [44, 55, 66, 77]
print 'P =', node.P
print 'x =', node.x
print 'x[1:3] =', node.x[1:3]
print '\nSetting node.x[1:3] = [100, 200]:'
node.x[1:3] = [100, 200]
print 'P =', node.P
print 'x =', node.x
print 'x[1:3] =', node.x[1:3]