python装饰器为什么要双层嵌套函数
PHPz
PHPz 2017-04-18 09:41:45
0
6
839

今天学习了一下python的装饰器,比较难理解的是大家举最简单的装饰例子时都是双层嵌套:

但是单层函数,不也能实现装饰功能吗?python把装饰器设置成双层的目的是什么呢?@到底代表什么运作机制。

PHPz
PHPz

学习是最好的投资!

全員に返信(6)
刘奇

上記の何人かの専門家が述べたように、デコレーター (@grammar) の機能は次のとおりです。

リーリー

は以下と同等です:

リーリー

を中国語に翻訳すると、次のようになります。

@で表される関数を引数として@関数を呼び出し、その値を@関数で表される関数名

に代入します。

このアクションは 装飾 (変更、拡張、調整、制限...) オリジナル bar に非常に似ているため、デコレーターと呼ばれます:

定義により、デコレータは別の関数を受け取り、後者の関数の動作を明示的に変更せずに拡張する関数です。

は装飾であると言われていますが、実行された bar は元の bar とは別人であり、foo はまったく新しいオブジェクト (通常は関数) を返しますが、その可能性は非常に高いです。返されるものは何もありません:

リーリー

上記の例では、foo は非常に奇妙なデコレータになっています。返されるのは None であり、装飾がないだけでなく、関数も破壊します。

最初に示した例に戻ります:

リーリー

あなたの foo には return ステートメントがありません。これは、fooNone を返すことを意味します (冗談です)。それは、@ 構文が登場した瞬間に、print 構文が実行されるからです。

しかし、

を呼び出そうとすると、エラーが発生することがわかります。func_a はまったく関数ではなく、もちろん、達成したい効果は再利用できません。 func_a


デコレーターは必ずしもローカル関数やネストされた関数を使用する必要はありませんが、通常はデコレーターに関数を返させることが非常に重要な点だと思います。結局のところ、装飾された関数は依然として関数です。

デコレーターは何千もあり、実際に関数の登録など、単一レイヤーのネストを使用できるものもあります。

リーリー

その理由は、このアクションは装飾中に一度だけ処理する必要があるため、関数を呼び出すたびに登録する必要はないからです。必要なのは元の関数だけです。

しかし、

ログの印刷時間の計算 などのアクションでは、関数を呼び出すたびに出力して計算する必要があるため、依然としてネスト手法を使用する必要があります。この関数はローカル関数によって作成されるため、必然的にカスケードとネストが生成され、2 レベル以上のネストを使用するパラメーターを持つより複雑なデコレーターもいくつかあります。 概要

ネストするかどうかは目的によって異なりますが、装飾後の関数を返すことを忘れないでください


私が回答した質問

: Python-QA

いいねを押す +0
迷茫

おそらく皆さんは私の考えが非常にわかりにくいと思います。なぜ Python がこのように設計されているのかということです。最初は単純なデコレータと 1 つの関数をネストするのは無駄だと思ったからです。ログや時刻などを出力するだけで十分です。これは Python の哲学ではありません。私は一晩考えて理解しましたが、困っている人は見てみてください。このデザインパターンの素晴らしさに。使用される逆推論手法では、基本要件を明確にしてから、各ステップがそのように記述されている理由を逆算して理解します。

リーリー
いいねを押す +0
Ty80
  1. デコレータは 定义 フェーズではなく 执行 で発生します。

  2. デコレーター関数
  3. を返す必要があります。outer被装饰的函数定义 ではなく 调用 を返す必要があることに注意してください。

  4. 階下の詳しい説明はとても良いです。
いいねを押す +0
刘奇

これは多くの人が共有したことがあるはずです。私も以前にブログを書きました。興味のあるトピックであれば、こちらをご覧ください。

Python デコレータの詳しい説明

いいねを押す +0
PHPzhong

リーリー

bar = foo(bar) と同等ですが、これだけを理解してください

いいねを押す +0
PHPzhong

2階は右です。barに値を代入する時点ですでに関数が実行されています。

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート