Goal
Я пытаюсь написать общую c оболочку, чтобы раскрыть элементы Python объектов, чтобы сделать их свойствами, чтобы их можно было использовать для привязки данных в WPF в форме Iron Python. Поскольку сценарий Iron Python выполняется внутри приложения. NET, у меня нет прямого доступа к определению объектов, только через интерфейс сценариев Iron Python, который их раскрывает.
Так как есть много объектов, которые я хочу выставить таким образом, с совершенно другой иерархией и структурой. Я хотел бы сделать мою оболочку как можно более общей c, написав для каждого объекта c оболочку.
Реализация
class MyObservable(object):
def __get(self, member):
print('Getting member %s' % member) # DEBUG
v = getattr(self.__object, member)
print('Value: ', v) # DEBUG
return v
def __init__(self, t):
self.__object = t
# Filter out private members
members = filter(lambda member: not(member.startswith('__')), dir(self.__object))
# Filter callable methods
try:
members = filter(lambda member: callable(getattr(self.__object, member)), members)
except SystemError:
# Ignore SystemError: Object has no member '__call__' exceptions on ScriptObject members
pass
for member in members:
v = self.__get(member) # DEBUG
print(member, v) # DEBUG
setattr(MyObservable, member, property(lambda self: v))
Тестовый пример (über упрощенный)
Ниже очень упрощенный тестовый пример, демонстрирующий мою проблему с простейшим макетом объекта python, который должен быть представлен:
>>> class Foo(object):
... def Test1(self):
... return 1
... def Test2(self):
... return 2
>>> test=MyObservable(Foo())
Getting member Test1
Value: <bound method Foo.Test1 of <Foo object at 0x00000000000002EF>>
Test1 <bound method Foo.Test1 of <Foo object at 0x00000000000002EF>>
Getting member Test2
Value: <bound method Foo.Test2 of <Foo object at 0x00000000000002EF>>
Test2 <bound method Foo.Test2 of <Foo object at 0x00000000000002EF>>
Проблема
Создание свойств работает должным образом, поскольку все они существуют и, кажется, повторяются правильно. Хотя второй экземпляр, кажется, ссылается на тот же объект, что и первый, несмотря на то, что он заявляет, что пытается получить правильный член.
>>> dir(test)
['Test1', 'Test2', '_MyObservable__get', '_MyObservable__object', '_MyObservable__set', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
>>>
Однако, когда я пытаюсь получить доступ к их значениям, я всегда получаю значение, возвращаемое из последнего набора элементов в течение __init__()
. В приведенном выше примере я получаю результат ниже:
>>> test.Test1
<bound method Foo.Test2 of <Foo object at 0x00000000000002EF>>
>>> test.Test1()
2
>>> test.Test2
<bound method Foo.Test2 of <Foo object at 0x00000000000002EF>>
>>> test.Test2()
2
>>>
Очевидно, назначение в __init__()
не работает должным образом, поскольку кажется, что для каждого члена назначается одна и та же ссылка.
Любой, кто может заметить моя ошибка? Предложения по другому рабочему подходу с учетом намеченной цели?