2

防止从 Python 调用(创建实例)C 类型的正确方法是什么?

我考虑过提供tp_init引发异常的 a ,但据我了解,它仍然允许__new__直接在类型上调用。

AC 函数返回这种类型的实例——这是创建这种类型实例的唯一方法。

编辑:我的意图是,如果他们不小心错误地使用了我的类型的用户,他们会得到一个例外。C 代码是这样的,在从 Python 错误创建的对象上调用函数会崩溃。我意识到这很不寻常:到目前为止,我所有的 C 扩展类型在从 Python 实例化时都运行良好。我的问题是是否有通常的方法来提供这种限制。

4

4 回答 4

3

简单:将类型的 tp_new 插槽留空。

>>> Foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot create 'foo.Foo' instances
>>> Foo.__new__(Foo)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object.__new__(foo.Foo) is not safe, use foo.Foo.__new__()

如果继承自基对象类型以外的类型,则必须在调用 PyType_Ready() 后将 tp_new 设置为 NULL。

于 2009-07-03T19:12:16.547 回答
1

不要阻止他们这样做。“我们都是同意这里的成年人。”

除非他们有理由,否则没有人会这样做,如果他们有这样的理由,那么您不应该仅仅因为您没有预料到您的类型的所有可能用途而阻止他们。

于 2009-07-03T15:36:27.533 回答
0

“该类型是另一个 C 函数的返回类型——这是创建这种类型实例的唯一方式”——这相当令人困惑。我认为您的意思是“AC 函数返回这种类型的实例——这是唯一的方法等等”。

在您的文档中,明确警告调用者不要调用该类型。不要从 C 扩展中导出类型。对于内省返回的实例的人,您无能为力,但那又怎样?这是他们的数据/机器/工作处于危险之中,而不是你的。

[更新(我讨厌用户界面的评论!)]

詹姆斯:“类型......只是从 C 中创建的”:你再次混淆了类型及其实例。该类型是在 C 中静态创建的。您的 C 代码包含该类型以及用户打算调用以获取该类型实例的工厂函数。由于某种你没有解释的原因,如果用户通过直接调用类型来获取实例,后续的 instance.method() 调用将崩溃(我想这就是你所说的“在对象上调用函数”的意思。叫我疯了,但这不是您应该修复的错误吗?

重新“不要出口”:尝试“不要暴露”。

在您的 C 代码中,您将拥有类似这样的内容,其中列出了模块提供的所有 API,包括类型和函数:

static struct PyMethodDef public_functions[] = {
   {"EvilType", (PyCFunction) py_EvilType, ......},
   /* omit above line and punters can't call it directly from Python */
   {"make_evil", (PyCFunction) py_make_evil, ......},
   ......,
   };

module = Py_InitModule4("mymodule", public_functions, module_doc, ...
于 2009-07-03T16:05:32.133 回答
0

有一种非常防弹的方法。让人们创建对象,并让 Python 崩溃。这应该会阻止他们非常有效地做到这一点。;)

您也可以在类名下划线,以表明它应该是内部的。(至少,我假设您也可以从 C 中创建带下划线的类名,但我实际上从未这样做过。)

于 2009-07-03T17:58:57.643 回答