簡體   English   中英

將pickle添加到用C ++編寫的Python擴展中

[英]Add pickle to a Python extension written in C++

我在C中編寫了一個Python擴展。它有效,沒問題。 現在我想用它來泡菜。 從文檔我很困惑。 我在這里為“擴展”編寫了一個測試__reduce__函數:

http://docs.python.org/library/pickle.html#the-pickle-protocol

我想念的是“可調用對象”應該是什么。 我試過PyObject_Type(self)的結果。 這是“可調用的”並且基本上可以工作,但是當對象被unickled時它會調用__init__ ,這給我帶來了一些麻煩。

有沒有任何標准的方法來調用只調用__new__方法的__new__ ,避免類初始化?

如果你調用__new__並且你使用type作為你的元類,如果__new__的結果是你的類型的子類型,將調用__init__ 換句話說,假設你有一個Foo類。 如果調用PyObject_Type(self)的結果,則與調用Foo()相同。 這意味着Foo。 將調用__new__ ,如果返回值是Foo的子類型,則將調用__init__

深入挖掘一下,當你調用Foo()時,它實際上是在調用type_call(在typeobject.c中),這就是tp_new后跟tp_init的內容。 如果直接提供對象的新函數(例如Foo_new()而不是PyObject_Type(self)),那么你在不調用__init__情況下調用__new__ ,你可以得到你想要的東西。 (不要忘記提供Foo作為__new__的參數)。

所以,最后回答你的問題,你可以簡單地調用Foo.__new__(Foo, ...) 這里有一些代碼可以滿足您的需求。

class Foo(object):
    def __new__(cls):
        return super(Foo, cls).__new__(cls)

    def __init__(self):
        print "__init__"

    def __reduce__(self):
        return (Foo.__new__, (Foo, ))

print "one"
x = Foo()              # prints __init__

print "two"
y = Foo.__new__(Foo)   # does not print __init__

print "three"
import pickle
p = pickle.dumps(Foo)
z = pickle.loads(p)    # does not print __init__

順便說一句,當我試圖弄清楚這一切時,我發現在幾乎所有情況下,我實際上可以實現我的代碼並允許調用__init__ 我的錯誤源於這樣一個事實:我沒有把那些進入__reduce__元組的第三個參數的東西分開。 為第二個參數提供任何內容都是完全可以的(假設__init__接受了這一點)並且只是在第三個參數中提供一堆將直接更新__dict__的東西。 如果你查看模塊和對象目錄中的cpython源代碼,你會看到__reduce__的許多實現,所有這些都以這種方式工作。

暫無
暫無

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

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