ローカルは何ですか?
threading.Localまたはwerkzeug.Localであるとあなたが接触するかどうか、彼らは変数を表す - それぞれが独自のグローバル変数をスレッド。
グローバル変数は、一般的にプロセス・ヒープにあります。彼らは、プロセスのアドレス空間を共有するためのプロセスのすべてのスレッドが、同じグローバル変数にアクセスすることができますので、各スレッドがアクセスすることができ、それはまた、複数のスレッドが同じ変数にアクセスする場合、これは意志、問題を提起します読み取りと書き込みの変数が予測できない結果を引き起こすので、通常我々は、スレッド間で共有変数へのアクセスを制御するロックまたは他の同期メカニズムを使用します。もちろん、これは地元紙の問題ではありません。
地元に戻って来て、私たちは地元が彼らのグローバル変数の先頭にスレッドであることを述べました。自分自身の、いわゆるスレッドは、それが他のスレッドが表示されていないためだけで、独自のスレッドへのアクセス権を持つ「グローバル変数」と言うことです。この定義を理解するには?シナリオを見てみましょう:完全な処理関数は、パラメータA治療ハンドラに、関数Bパラメータは、それが機能B. Aに渡されたパラメータは必須の機能です C関数は、それのパラメータに対処する必要がある場合、それはDに機能すべきか?そして、パラメータAは、これらの関数の間で渡されていきますが、また、事前に生活の際に、これらの機能を優れたパラメータを宣言しました。一つは、関数間で渡されるパラメータがある場合は、機能は非常に複雑で、非常に複雑な関数呼び出しになることを想像することができます。それを行うための簡単な方法はありませんか?
実際には、我々はこのパラメータを作るために、視覚機能のために必要とされる、関数のパラメータとの間を通過し、それはあなたがする必要はありませんグローバル変数に変わるのでしょうか?しかし、グローバル変数になるために、他のスレッドは、私はちょうど独占それをしたい、それがこのスレッドの意図ではない、その値を変更することがあり、私のグローバル変数にアクセスする必要があります。この時点で、私たちはこのスレッドの変数が関係している必要がある、それは他のスレッドのためのプロセスの観点では、グローバル変数である必要があり、それはローカル変数のように見えます。これは、ローカルは、1つのそのような変数であり、シナリオの種類ローカルの使用です。
あなたがグローバルドメイン内でローカルに定義する場合、これは本当にローカル、グローバル変数ではなく、各スレッドは変数にアクセスし、このスレッドは、実際には、対応するローカルを取得します。この効果を達成するためにどのように?実際には、ローカル変数自体は非常に簡単ではありません、それはまた、操作の数が含まれています。あなたはそれをこのように解釈することができ、各プロセスがグローバル辞書を持って、各スレッドは、独自のスレッドID自体を持って、プロセスのすべてのスレッドは、グローバル辞書にアクセスすることができ、それらは重要な辞書としてのスレッドIDを入れて、何かが値として格納する必要があり、唯一の自分のキーで辞書にアクセスすることができ、各スレッドは、その値自体が排他的グローバル変数スレッドに相当します!それは違うのですか?奇妙な各スレッドは、グローバル変数の雌ねじに相当し、独自の、世界的なもの、のようなものを取ります。特定のコードの実装は異なりますが、一般的にこのアイデア。
クラスローカル(オブジェクト): __slots__は=( '__storage__'、 '__ident_func__')である DEF __init __(自己): オブジェクト.__ SETATTR __(自己、 '__storage__'、{})#保存する事グローバル辞書 オブジェクト.__ SETATTR __(自己、「 __ident_func__ 」、get_ident)#キーの各スレッド DEF __iterの__(自己): (セルフ.__ストレージ__項目(ITERを返す。)) DEF __call __(自己、プロキシ): 。"名前のプロキシを作成します。" "" "" LocalProxyを返しますここで(セルフ、代理)#LocalProxyオブジェクトを返すように、LocalProxyは、プロキシ、プロキシローカルオブジェクトです。 __ __release_local DEF(自己): 。セルフストレージ__ .__ POP(自己.__ ident_func __()、なし) DEF __getattr __(自己、名): 試し: 自己を返します。 KeyError例外を除い: はAttributeError(名前を)上げる デフ__setattr __(自己、名前、値): IDENT =自己.__ ident_func __() ストレージ=自己.__ storage__の 試み: ストレージ[IDENT] [名] =値 KeyError例外を除い: ストレージ[IDENT] = {名前:値} defは__delattr __(自己、名): 試してください: デル自己.__ストレージ__ [自己.__ ident_func __()] [名前] KeyError例外を除い: はAttributeError(名前を)上げます
ローカルどのように使用するには?
擬似コード
ローカル=ローカル() local.request =「私がリクエストAM」 local.response =「私は応答AM」 DEF仕事(): local.request XXXX =#各スレッドは、自分の要求および応答にアクセスできるようになります local.response = XXXX#でも応答を変更、ちょうどこのスレッドの値を変更 __name__ == "__main__" IF: 範囲内の私のために(10): スレッド(ターゲット=仕事).start()
グローバルローカルオブジェクトを宣言することで、その後、あなたが残したい同じ値へのアクセスのようなオブジェクトの属性にアクセスします。あなたは、辞書のローカル相当するものを理解することができ、私は値を取得するためにそのコールlocal.keyを必要とする値にアクセスするためのキーによって自分自身を定義したいです。このような使用は、時々、よくわかっていない、明らかに私は書くために、彼らはアクセスのように、オブジェクトの属性になり、非常に奇妙な定義された値よ、非常に厄介です。あなたはそれのローカル変数を直接使用としてグローバル変数として定義することはできませんか?
#私はこの効果たい 要求=「私がリクエストAM」 「私はレスポンスAM」=レスポンスを
それは方法を__call__使用していることのローカル__call__方法は、我々はグローバル変数などの地元のルックスになることができます。
#あなただけのメソッドローカルオブジェクトを__call__呼び出す必要があります )(ローカル=ローカル local.request =「私がリクエストAM」 ここで文字列が必要に渡され、上記の時間を節約することmy_request =ローカル(「要求」)#(注)一貫性のある
my_request番号「私は要求しています」
local.requestに比べ、local.requestにmy_request今同等、my_requestは、より多くのグローバル変数のように見えませんか?しかし、それは、覚えている「ユニークなグローバル変数を通します。」
何がそれをLocalProxy?
辞書のローカル同等のが、xのlocal.xこのエスクローとローカルキー、およびキーLocalProxyに対応し、私たちはLocaProxy自体を訪問し、それが自動的にローカル辞書で見つかった値にキーを取得するために使用され、私たちに戻って、これは、エージェント(代理人)であります
my_request実際LocalProxy、直接アクセスmy_requestは、それが文字列「私は要求しています」です。私たちは、私は、このようなローカルオブジェクトとしてグローバル変数を、必要とするローカルストアに値が任意の値を格納することができ、辞書のように見える=ローカルオブジェクトがlocal.xxxすることができます言及しました。しかし、すべての時間が、我々は価値あまりにも多くの問題を取得したい、私たちは私たちは、この繰り返し操作を完了を支援するオブジェクトを必要とする、それへの鍵は、辞書にそれを持って、私はちょうどlocal.xxxを介してアクセス、辞書にキーの値によってそれを確認し、その後、値が私に返されます。それは私のためである。この方法は、格納された値そのものが好き。これは、エージェントです。
LocalProxy原理はそう、それは私たちが現地の値にする方法を見つけるのに役立つなかったので、我々はlocal.xxx保存したいとき、「xxxは」これは、その後、地元の代理店そのものを伝える伝えるために現地代理店を開くための鍵となるようなものですLocalProxyは、鍵を持って、あなたは自然に彼が私達に戻ってドアの内側に詰め込むことができ、扉を開きたいです。この観点から、地方自身がプロキシとしても見ることができ、そのプロキシは、グローバル変数のスレッドである、そしてそれはキーがスレッドのIDで保持し、それがこのスレッドがグローバル見つけグローバル辞書にIDを渡しますその後、変数、私たちに戻りました。
クラスLocalProxy(オブジェクト): __slots__ =( '__local'、 '__dict__'、 '__name__'、 '__wrapped__') デフ__init __(自己、ローカル、名前=なし): オブジェクト.__ SETATTR __(自己、 '_LocalProxy__local'、ローカル)#要打开的门 オブジェクト.__ SETATTR __(自己'__name__'、名前)#钥匙 (ローカル、 '__release_local__を')はhasattr呼び出し可能(ローカル)とそうでない場合: # "ローカル"はローカルまたはのインスタンスではないという呼び出し可能です # LocalManager:包まれた機能としてそれをマーク。 オブジェクト.__ SETATTR __(自己、 '__wrapped__'、地元の) デフ_get_current_object(自己): 「」 "現在のオブジェクトを返しますあなたは本当をしたい場合に便利です ""」 (自己.__ローカル、 '__release_local__')はhasattrない場合: 戻り自己.__ローカル() してみてください: リターンのgetattr(自己.__ローカル、自己.__ name__)#1通过キー(名)到字典(ローカル)中获取値 を除きますAttributeError: はRuntimeError(%自己.__ name__ '%sのにバインドされていないオブジェクト')上げ @property :デフ__dict __(自己) してみてください: 戻りself._get_current_object().__ dict__に はRuntimeErrorを除く: はAttributeError( '__ dict__に')上げ デフ__repr __(自己): 試してみてください。 OBJ = self._get_current_object() はRuntimeErrorを除く: リターン'<%sの結合していない>' %の自己.__クラス__.__ name__ 例外RuntimeErrorを除いた: 返します[ ] リターンのrepr(OBJ) デフ__bool __(自己): 試してください: リターン・ブール(self._get_current_object()) はRuntimeErrorを除く: Falseを返す デフ__unicode __(自己): 試してください: リターンユニコード(self._get_current_object())#のnoqa はRuntimeErrorを除く: リターンrepr(セルフ) デフ__dir __(自己): 試してください: リターンDIR(self._get_current_object()) デフ__getattr __(自己、名): もし名前== '__members__': リターンDIR(self._get_current_object()) 并、GETATTR返す(self._get_current_object()、名前)#1通过キー(名)到字典(ローカル)中去查找真正的価値返回 デフ__setitem __(自己、キー、値): self._get_current_object()[キー] =値 DEF __delitem __(自己、鍵): デルself._get_current_object()[キー] PY2場合: __getslice__ =ラムダX、I、J:x._get_current_object()[I:J] DEF __setslice __(自己、I、J、SEQ ): self._get_current_object()[I:J] =配列 DEF __delslice __(自己、I、J): デルself._get_current_object()[I:J] __setattr__ =ラムダX、N、V:SETATTR(x._get_current_object( )、N、V) __delattr__ =ラムダX、N:delattr(x._get_current_object()、N)
LocalProxy一般的な方法の一部を達成するために自分自身をLocalProxyている多くの方法がありますが、これらの方法は、それ自体へのコールが、エージェント値への呼び出しではありません。
我々は本質的に同じであるが、建設LocalProxyのローカル__call__メソッドを呼び出すことはできませんコンストラクタ関数LocalProxyによって直接LocalProxyすることができます。
=)(ローカルローカル local.request =「要求」 my_request = LocalProxy(ローカル、「要求」)と二番目の引数#1 XXXには同じであるlocal.xxx
何がそれをLocalStack?
ちょうどローカル辞書などの地元LocalStackと同じ、。LocalStackは、スタックではなく、データを格納するのと同じ方法です。これは、ユニークなグローバルスレッド・スタックと見なすことができます。プロセスの他のスレッドによる干渉を気にせずにそれを使用してください。
クラスLocalStack(オブジェクト): デフ__init __(自己): (ローカル= self._local) デフ__release_local __(自己): self._local .__ release_local __() デフ_get__ident_func __(自己): 戻りますself._local .__ ident_func__ デフ_set__ident_func __(自己、値): オブジェクト.__ SETATTRの__(self._local、 '__ident_func__'、値) __ident_func__ =プロパティ(_get__ident_func__、_set__ident_func__) デル_get__ident_func__、_set__ident_func__ デフ__call __(自己): デフ_lookup(): RV = self.top RVがNoneの場合: 昇給RuntimeError( 'オブジェクト結合していない') 戻りRV LocalProxy(_lookupを)返し ます:def(自己が、OBJ)押す "" "" "スタックに新しいアイテムをプッシュ" RV = GETATTR(self._local、 'スタック'、なし) RVがNoneの場合: self._local.stackを= RV = [] rv.append(OBJ) の戻りRVの デフポップ(自己): 「」「スタックから一番上の項目を削除し、返します スタックがすでに空だった場合、古い値または`NONE`を。 『』」 スタックを= GETATTR(self._local、 'スタック'、なし)は 、スタックがNone場合: なし戻りません :のelif lenは(スタック)== 1 release_local(自己を。_local) リターンスタック[-1] 他: リターンstack.pop() @property defをトップ(自己): 「」「スタックの一番上のアイテムのスタックは、空の場合。 `NONE`が返されます。 『』」 してみてください: 戻りself._local.stackを[ -1] (はAttributeError、はIndexError)を除い: Noneを返します
地元の違いとスレッドセーフ
現地では、複数のスレッドが同じグローバル変数、および時にスレッドの排他的グローバル変数はローカル代表は、他のスレッドのために懸念しているにアクセスしたときに、スレッドセーフ(スレッドセーフな)は、スレッドの安全性は、同期メカニズムをより重視であることを意味するものではありません見えないので不安スレッドの安全性の問題がある存在しません。ローカル永遠にそれはこのスレッドで動作しますので、あなたは、単に定義を望んでいたならば、それはスレッドセーフです。