![](/img/trans.png)
[英]Python receives SIGSEGV while loading C++ written extension module
[英]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.