Рекурсивно обходя дерево наследования Python во времени выполнения

Я пишу некоторый код сериализации/десериализации в Python, который будет чтение-запись иерархия наследования от некоторого JSON. Точный состав не будет известен, пока запрос не представляется.

Так, я считаю изящное решение рекурсивно анализировать иерархию классов Python, которая будет испускаться и затем, на пути создают резервную копию через дерево, устанавливают правильные значения в основном типе Python.

E.g.,

A
|
|\
| \
B  C

Если я называю мой "анализировать" стандартную программу на B, она должна возвратить dict, который содержит отображение от всех переменных A к их значениям, а также переменных B и их значениям.

Поскольку это теперь стоит, я могу просмотреть B.__slots__ или B.__dict__, но я только могу вытащить имена переменной B оттуда.

Как я добираюсь __slots__/__dict__ из A, учитывая только B? (или C).

Я знаю, что Python непосредственно не поддерживает кастинг как C++, и его потомки делают -

8
задан Paul Nathan 23 July 2010 в 20:06
поделиться

2 ответа

Вы можете попробовать использовать метод type.mro(), чтобы найти порядок разрешения метода.

class A(object):
        pass

class B(A):
        pass

class C(A):
        pass

a = A()
b = B()
c = C()

>>> type.mro(type(b))
[<class '__main__.B'>, <class '__main__.A'>, <type 'object'>]
>>> type.mro(type(c))
[<class '__main__.C'>, <class '__main__.A'>, <type 'object'>]

или

>>> type(b).mro()

Edit: Я подумал, что вы хотите сделать что-то вроде этого...

>>> A = type("A", (object,), {'a':'A var'})  # create class A
>>> B = type("B", (A,), {'b':'B var'})       # create class B
>>> myvar = B()

def getvars(obj):
    ''' return dict where key/value is attribute-name/class-name '''
    retval = dict()
    for i in type(obj).mro():
        for k in i.__dict__:
            if not k.startswith('_'):
                retval[k] = i.__name__
    return retval

>>> getvars(myvar)
{'a': 'A', 'b': 'B'}

>>> for i in getvars(myvar):
    print getattr(myvar, i)   # or use setattr to modify the attribute value

A Var
B Var
12
ответ дан 5 December 2019 в 12:07
поделиться

Не могли бы вы уточнить, что вы ищете?

На данный момент ваше описание вообще не описывает Python. Предположим, что в вашем примере A, B и C являются именами классов:

class A(object) :
...     def __init__(self) :
...             self.x = 1
class B(A) :
...     def __init__(self) :
...             A.__init__(self)
...             self.y = 1

Тогда экземпляр среды выполнения может быть создан как:

b = B()

Если вы посмотрите словарь объекта среды выполнения, то он не будет различать его собственные переменные и переменные, принадлежащие его суперклассу. Так например: dir (b)

[ ... snip lots of double-underscores ... , 'x', 'y']

Итак, прямой ответ на ваш вопрос состоит в том, что это уже работает так, но я подозреваю, что это не очень помогает вам. Что не отображается, так это методы, поскольку они являются записями в пространстве имен класса, а переменные находятся в пространстве имен объекта. Если вы хотите найти методы в суперклассах, используйте вызов mro (), как описано в предыдущем ответе, а затем просмотрите пространства имен классов в списке.

Пока я искал более простые способы сериализации JSON, я обнаружил некоторые интересные вещи в модуле pickle.Одно из предложений состоит в том, что вы можете захотеть мариновать / распаковывать объекты, а не писать свои собственные для обхода иерархии. Результатом pickle является поток ASCII, и вам может быть проще преобразовать его туда и обратно в JSON. В PEP 307 есть несколько отправных точек.

Еще одно предложение - взглянуть на метод __ reduce __ , попробовать его на объектах, которые вы хотите сериализовать, поскольку это может быть именно то, что вы ищете. .

2
ответ дан 5 December 2019 в 12:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: