web-dev-qa-db-ja.com

dictproxyの目的は何ですか?

型の__dict__は、読み取り専用のdictproxyオブジェクトです。その目的が何なのか知りたい。 「組み込み型の変更を許可しない」ためだけですか?これを回避できる方法を見つけました。組み込み型を変更するのは良い考えではないことを私は知っています。しかし、私はCythonのcdef classをオンザフライで変更しようとしています。

__dict__cdef classをこのように変更するのに危険なものはありますか?

コードは次のとおりです。

import gc
gc.get_referents(float.__dict__)[0]["square"] = lambda self: self*self
(3.14).square()
21
HYRY

dictproxy(クラスにあります)の目的は、Pythonインタープリターでの最適化を可能にし、その安定性を確保することです。最適化の要件の詳細については、以下のMartijnPietersコメントを参照してください。 、明らかにclass.__dict__のキーは常に文字列であることに依存しています。

dictproxyは、インタプリタの特定の不安定性から保護する役割も果たしているようです。このような不安定性の詳細については、python.orgで「 __ dict__読み取り専用のバイパス 」というタイトルで説明されているバグレポートとバグ修正を参照してください。ある種のプロキシメカニズムを使用しない場合は、__dict__に書き込むことができます。書き込み可能であれば削除可能です。バグレポートでは、__dict__が削除され、インタプリタがクラッシュする可能性があるいくつかのシナリオについて説明しています。

これは、canが直接または__setitem__()

  • instance.__dict__['x'] = 1

また、インスタンス__dict__は削除できます。削除された場合、属性の割り当てが試行されたときに自動的に再作成されます。

del instance.__dict__ instance.a = 1 instance.__dict__

結論

つまり、dictproxyを使用すると、クラスがより最適に動作し、インタープリターがより安定します。

17
Scott H

__dict__は、クラス属性を保持する名前空間オブジェクトです。

__dict__自体を変更しない限り、dictオブジェクトの変更に問題はありません。

例:

//good
MyClass.x = 1 

//bad
MyClass.__dict__['x'] = 1

//good
m = MyClass()
m.x = 1

//also good
m.__dict__['x'] = 1

Pythonドキュメント[ [〜#〜] link [〜#〜] ]:Attribute assignment updates the module’s namespace dictionary, e.g., m.x = 1 is equivalent to m.__dict__["x"] = 1.

したがって、dictのオブジェクトを変更しても問題はありません。

さらに:

クラスの属性を変更できるため、クラスのdictは常に書き込み可能です。

__dict__ | The namespace supporting arbitrary function attributes. | Writable

Cpythonの実装はpyhtonとは少し異なる可能性がありますが、ドキュメントから読み取れるように、言及されていません。

6
Persijn