Я пишу некоторый код сериализации/десериализации в 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++, и его потомки делают -
Вы можете попробовать использовать метод 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
Не могли бы вы уточнить, что вы ищете?
На данный момент ваше описание вообще не описывает 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 __
, попробовать его на объектах, которые вы хотите сериализовать, поскольку это может быть именно то, что вы ищете. .