簡體   English   中英

如何處理從Web API構建的具有相互引用的python對象?

[英]How to handle python objects built from a web API that have references to each other?

我正在為Web API構建客戶端庫,該庫公開了一些這樣的對象:

# objs/foo/obj_id_1
{id: "foo_id_1"
 name: "your momma"
 bar: "bar_id_2"}

# objs/bar/obj_id_1
{id: "bar_id_2"
 name: "puh-lease"
 foo: "foo_id_1"}

因此, foo類型的對象引用了bar類型的對象,反之亦然。

在我的python客戶端庫中,我根據此API數據構建了python對象。 一個Foo實例將具有一個包含Bar實例的bar屬性,而不僅僅是bar的ID,並且一個Bar實例在foo屬性中具有對Foo實例的引用。

我的python類具有saverefresh方法,這些方法可以從Web API進行POST或GET,並且它們對子對象執行此操作。 例如,如果我調用a_foo.refresh() ,它也會自動調用a_foo.bar.refresh()

上面是一個非常簡化的示例,可能有許多不同的類都引用barfoo或我們得到的許多其他類型的對象的同一實例。

我認為我的問題實際上是兩個問題:

  1. 有什么好的設計或策略可以確保,如果我已經根據以前的api請求構建了該對象,那么當我從api數據構建對象時,該對象對其他對象的所有引用都指向同一個對象嗎?
  2. 當我調用saverefresh時,當兩個或多個對象相互引用時,防止無限循環的最佳設計或策略是什么?

這是一個相當廣泛的問題。

1)一種方法是使用工廠方法模式。 例:

def get_foo(_id):
    get_foo.foos = dict()
    def real_get_foo(_id):
        # get foo from the API
        get_foo.foos[_id] = foo
        return foo
    if _id in get_foo.foos:
        return get_foo.foos[_id]
    return real_get_foo(_id)

2)我認為進行嵌套保存不是一個好主意。 如果我先寫foo.bar.x = 5然后foo.save()我不會期望bar被保存。 為什么? 因為我在foo上調用了save() ,所以我不必擔心對相關對象進行不必要的保存。

對於#1,您可以使用2級字典來保存獲取的對象

objectCache
    |- foo 
    |   |- foo_id_1 : <obj>
    |   |- foo_id_2 : <obj>
    |   |- ...
    |
    |- bar
    |   |- bar_id_1: <obj>
    |   |- bar_id_2: <obj>
    |   |- ...
    |   
    |- baz
    |   |- baz_id_1: <obj>
    |   |- baz_id_2: <obj>
    |   |- ...
    |
    |- ...

您可以這樣使用它:

def get_or_make_fetched_object(cls, id):
    return object_cache.setdefault(cls, {}).setdefault(id, cls())

my_foo = get_or_make_fetched_object(Foo, 'foo_id_1')

這里的技巧部分是如何擺脫不再引用的對象(例如,如果foo_id_1從bar_id_1切換到bar_id_35),以避免內存泄漏,因為object_cache字典將無限期保留對該對象的引用,除非從該對象中刪除該對象。緩存。

解決內存使用問題的一種可能方法是使用gc.get_referrers()獲取每個緩存對象的refcount的清理函數。 基本上,緩存中具有refcount等於2的對象可以從緩存中刪除(1個計數來自gc ,另一個來自緩存)。 不過,這不適用於循環引用...

對於#2,您可以為帶有保存日期的對象添加時間戳,與當前保存時間戳匹配的對象將被跳過,以避免無限遞歸。 但是,僅保存下級對象是有意義的。

暫無
暫無

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

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