Динамически добавленные свойства всегда возвращают значение последнего члена, обработанного в __init__ - PullRequest
1 голос
/ 06 августа 2020

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__() не работает должным образом, поскольку кажется, что для каждого члена назначается одна и та же ссылка.

Любой, кто может заметить моя ошибка? Предложения по другому рабочему подходу с учетом намеченной цели?

...