簡體   English   中英

如何從其屬性之一的值檢索類的實例?

[英]How can I retrieve the instance of a class from a value of one of its attributes?

我想(優雅地)序列化不同類實例中屬性之間的連接。 例如:

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>

在這種情況下,盡管我也想找到out_obj類的out_obj實例和屬性名稱foo 如果將self'foo'傳遞到AttrClass初始化中,則可以完成此操作,但這對於用戶每次使用該類作為值創建新屬性時繼續輸入它都是令人討厭的。

有沒有一種方法可以從一個值追溯到屬性名稱,即屬性的值以及該屬性所屬的類實例?

另外,有沒有一種方法可以在實例化時自動將類實例和屬性名稱添加到類中? 例如:

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'

您不能,至少不能優雅地-可以用很多inspect魔術來做到這一點,但是它很快就會變得丑陋。 這個“問題”幾乎存在於所有依賴於解釋器/ 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

妳去 該代碼的保證為零,因為它依賴於解釋器實現中的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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM