我想(优雅地)序列化不同类实例中属性之间的连接。例如:
class AttrClass(object):
def __init__(self, value=None):
self.value = value
class ObjClass(object):
def __init__(self, name, value=None):
self.name = name
self.foo = AttrClass(value=value)
out_obj = ObjClass('out', value='bar')
in_obj = ObjClass('in', value=out_obj.foo)
in_obj.foo
# Result: <AttrClass object at 0x000001B086B0A470>
在这种情况下,我还想找到ObjClass类的out_obj
实例和属性名foo
。如果self
和'foo'
被传递到AttrClass初始化,那么可以这样做,但是每次用户创建一个以该类为值的新属性时,用户都会继续输入它。 p>
有没有一种方法可以追溯一个值到属性名称,它是值和属性所属的类实例?
或者,有没有一种方法可以在实例化时自动将类实例和属性名称添加到类中?例如:
class AttrClass(object):
def __init__(self, value=None):
self.value = value
self.host_class = self.do_magic_class_thing()
self.host_attr = self.do_magic_attr_thing()
out_obj = ObjClass('out', value='bar')
in_obj = ObjClass('in', value=out_obj.foo)
in_obj.foo.host_class.name
# Result: 'out'
答案 0 :(得分:0)
你不能,至少不是优雅 - 你可以用很多inspect
魔法做到这一点,但它会变得非常丑陋很快。这个问题&#39;存在于几乎所有语言中,依赖于他们的解释器/ VM来通过引用计数进行内存管理 - 如果对象的子项要存储对父母的引用,则会得到一个不能快速解决的循环引用计数,并且因为语言设计师通常会选择不这样做,而是让开发人员处理他们自己的特定情况。
因此,在您的特定情况下,由于您正在包装您的值AttrClass
实例,您可以让这些实例保持对其父母的引用:
class AttrClass(object):
def __init__(self, parent, value=None):
self.parent = parent
self.value = value
class ObjClass(object):
def __init__(self, name, value=None):
self.name = name
self.foo = AttrClass(self, value=value)
out_obj = ObjClass('out', value='bar')
in_obj = ObjClass('in', value=out_obj.foo)
assert in_obj.foo.value.parent is out_obj # passes
print(in_obj.foo.value.parent.name) # out
另外,为什么需要编写自己的序列化器/反序列化器有什么特别的原因吗?那里有很多这样的东西,我确信至少有一些适合你的用例。我全心全意地推荐MessagePack。
答案 1 :(得分:0)
你去吧。此代码没有任何保证,因为它依赖于解释器实现中的Python堆栈帧支持。
import inspect, re
class AttrClass(object):
def __init__(self, value=None):
self.value = value
stack = inspect.stack() # get the stack
goback = stack[2] # go down the stack 2 step
entry_point = goback[4] # get the code context to get "object name" [4] is from stack format
name = re.findall("ObjClass\(.*value=([^)]*)\)", entry_point[0]) # magic hack to get "out_obj"
if len(name) > 0:
obj_name = name[0].split('.')[0] # get the object's name.
argvalues = inspect.getargvalues(goback.frame)[3] # [3] to get `locals` from tuple returned.
if obj_name in argvalues:
setattr(self, 'host_class', argvalues[obj_name]) # iject the attribute
else: #Sorry can't find it
setattr(self, 'host_class', None)
class ObjClass(object):
def __init__(self, name, value=None):
self.name = name
self.foo = AttrClass(value=value)
out_obj = ObjClass('out', value='bar')
in_obj = ObjClass('in', value=out_obj.foo)
print(in_obj.foo.host_class.name)