2

Python から C 型を呼び出す (インスタンスを作成する) ことを防ぐ正しい方法は何ですか?

tp_init例外を発生させる を提供することを検討しましたが、私が理解しているよう__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

素晴らしい防弾方法があります。人々にオブジェクトを作成させ、Python をクラッシュさせます。それは彼らがそれをかなり効率的に行うのを止めるはずです. ;)

また、クラス名にアンダースコアを付けて、内部であることを示すこともできます。(少なくとも、C からも下線付きのクラス名を作成できると思いますが、実際に行ったことはありません。)

于 2009-07-03T17:58:57.643 に答える
0

「この型は別の C 関数の戻り値の型です。これが、この型のインスタンスを作成する唯一の方法です」 - これはかなり紛らわしいです。「AC関数はこのタイプのインスタンスを返します-それが唯一の方法などです」という意味だと思います。

ドキュメントで、型を呼び出さないように呼び出し元に明確に警告します。C 拡張機能から型をエクスポートしないでください。返されたインスタンスを内省する人についてはあまり何もできませんが、それで何ですか? 危険にさらされているのは彼らのデータ/マシン/ジョブであり、あなたのものではありません.

[更新(コメントのUIが嫌い!)]

James: "type ...ちょうど 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 に答える