在不调用 __init__ 的情况下初始化 PyObject
Initialize PyObject without calling __init__
我有一个包装器 class,如下例所示,用 Python.
编写
class Foo:
def __init__(self, bar=None):
if bar:
self._bar = bar
else:
self._bar = CreateBarObject("value")
我通过 Python C API
创建了一个实例
// c++ pseudo code for convenience
auto obj = PyObject_CallObject(Foo)
auto bar = CreateBarObject("another_value");
PyObject_SetAttrString(obj, "_bar", bar)
正如您从代码中看到的,Foo.__init__
将在创建一个创建新 bar
对象的实例时被调用。但是我想绕过这个 "heavy" 操作。那么有什么安全的方法可以创建 Foo 的实例,这样我就可以通过 Python C API 设置 self._bar
?有什么想法吗?
将 self.bar
设为 属性,在第一次需要时创建实例。
class Foo:
def __init__(self, bar=None):
self._bar = bar
@property
def bar(self):
if self._bar is None:
self._bar = CreateBarObject(...)
return self._bar
实例功能齐全。实例的 bar
属性 将在第一次需要时创建 Bar
对象。或者你可以在这之前从 C API 设置 _bar
,然后使用它。或者您可以在实例化 class 时传入现有的 Bar
对象。你的选择。
你应该可以直接调用Foo
的the tp_new
(相当于在Python层调用Foo.__new__
)。这将执行分配和 C 级 "mandatory initialization" 工作,而没有 tp_init
/__init__
的 "optional initialization" 工作。这与 pickle
用于创建类型实例而不初始化它们的策略相同(因此它可以通过 __setstate__
或直接填充它们 __dict__
,视情况而定)。
假设 Foo
是 C 级 PyTypeObject*
,这样的事情应该可以解决问题:
auto emptytup = PyTuple_New(0); /* AFAICT, the args tuple is mandatory, but kwargs is optional */
/* Error check for PyTuple_New failure */
auto obj = Foo->tp_new(Foo, emptytup, NULL);
Py_DECREF(emptytup);
/* Error check for new fail */
auto bar = CreateBarObject("another_value");
PyObject_SetAttrString(obj, "_bar", bar)
我有一个包装器 class,如下例所示,用 Python.
编写class Foo:
def __init__(self, bar=None):
if bar:
self._bar = bar
else:
self._bar = CreateBarObject("value")
我通过 Python C API
创建了一个实例// c++ pseudo code for convenience
auto obj = PyObject_CallObject(Foo)
auto bar = CreateBarObject("another_value");
PyObject_SetAttrString(obj, "_bar", bar)
正如您从代码中看到的,Foo.__init__
将在创建一个创建新 bar
对象的实例时被调用。但是我想绕过这个 "heavy" 操作。那么有什么安全的方法可以创建 Foo 的实例,这样我就可以通过 Python C API 设置 self._bar
?有什么想法吗?
将 self.bar
设为 属性,在第一次需要时创建实例。
class Foo:
def __init__(self, bar=None):
self._bar = bar
@property
def bar(self):
if self._bar is None:
self._bar = CreateBarObject(...)
return self._bar
实例功能齐全。实例的 bar
属性 将在第一次需要时创建 Bar
对象。或者你可以在这之前从 C API 设置 _bar
,然后使用它。或者您可以在实例化 class 时传入现有的 Bar
对象。你的选择。
你应该可以直接调用Foo
的the tp_new
(相当于在Python层调用Foo.__new__
)。这将执行分配和 C 级 "mandatory initialization" 工作,而没有 tp_init
/__init__
的 "optional initialization" 工作。这与 pickle
用于创建类型实例而不初始化它们的策略相同(因此它可以通过 __setstate__
或直接填充它们 __dict__
,视情况而定)。
假设 Foo
是 C 级 PyTypeObject*
,这样的事情应该可以解决问题:
auto emptytup = PyTuple_New(0); /* AFAICT, the args tuple is mandatory, but kwargs is optional */
/* Error check for PyTuple_New failure */
auto obj = Foo->tp_new(Foo, emptytup, NULL);
Py_DECREF(emptytup);
/* Error check for new fail */
auto bar = CreateBarObject("another_value");
PyObject_SetAttrString(obj, "_bar", bar)