Python は初心者に優しい言語です。ただし、デコレータなど、使いこなすのが難しい高度な機能も数多くあります。多くの初心者は、デコレータとその仕組みを理解したことがありません。この記事では、デコレータの詳細を紹介します。
Python では、関数は非常に柔軟な構造であり、変数に代入したり、パラメータとして別の関数に渡したり、関数の出力として使用したりできます。デコレーターは本質的に、他の関数が変更せずに機能を追加できるようにする関数です。
これは「装飾」の意味です。この「装飾」自体が機能を表します。別の機能を変更するために使用される場合、その機能をそれらの機能に追加します。
一般的に、デコレータが提供する @ 構文シュガー (Syntactic Sugar) を使用して、他の関数やオブジェクトを装飾できます。以下に示すように、@dec デコレータを使用して関数 func () を装飾します:
@dec def func(): pass
デコレータを理解する最良の方法は、デコレータがどのような問題を解決するかを理解することです。この記事では、デコレータを段階的に紹介します。特定の問題から出発し、その優雅さと力を誇示します。
問題の設定
デコレータの目的を理解するために、簡単な例を見てみましょう。 2 番目のパラメーターのデフォルト値が 10 である単純な加算関数 dec.py があるとします。
# dec.py def add(x, y=10): return x + y
この加算関数を詳しく見てみましょう:
>>> add(10, 20) 30 >>> add <function add at 0x7fce0da2fe18> >>> add.__name__ 'add' >>> add.__module__ '__main__' >>> add.__defaults__ # default value of the `add` function (10,) >>> add.__code__.co_varnames # the variable names of the `add` function ('x', 'y')
必要はありません。これらが何であるかを理解するには、Python のすべての関数がオブジェクトであり、さまざまなプロパティとメソッドがあることを覚えておいてください。また、検査モジュールを使用して add() 関数のソース コードを表示することもできます:
>>> from inspect import getsource >>> print(getsource(add)) def add(x, y=10): return x + y
ここで、何らかの方法で加算関数を使用します。たとえば、いくつかの操作を使用して関数をテストします:
# dec.py from time import time def add(x, y=10): return x + y print('add(10)', add(10)) print('add(20, 30)', add(20, 30)) print('add("a", "b")', add("a", "b")) Output: i add(10) 20 add(20, 30) 50 add("a", "b") ab
各操作の時間を知りたい場合は、time モジュールを呼び出すことができます:
# dec.py from time import time def add(x, y=10): return x + y before = time() print('add(10)', add(10)) after = time() print('time taken: ', after - before) before = time() print('add(20, 30)', add(20, 30)) after = time() print('time taken: ', after - before) before = time() print('add("a", "b")', add("a", "b")) after = time() print('time taken: ', after - before) Output: add(10) 20 time taken:6.699562072753906e-05 add(20, 30) 50 time taken:6.9141387939453125e-06 add("a", "b") ab time taken:6.9141387939453125e-06
さて、プログラマとして、少しかゆいところはありませんか? 結局のところ、私たちはコピーしたくないのです。常に同じコードを貼り付けます。現在のコードはあまり読みにくくなっています。何かを変更したい場合は、表示されている箇所をすべて変更する必要があります。Python にはもっと良い方法があるはずです。
次のように、追加関数で実行時間を直接取得できます。
# dec.py from time import time def add(x, y=10): before = time() rv = x + y after = time() print('time taken: ', after - before) return rv print('add(10)', add(10)) print('add(20, 30)', add(20, 30)) print('add("a", "b")', add("a", "b"))
この方法は、前の方法よりも明らかに優れています。しかし、別の機能がある場合、これは不便に思われます。複数の関数がある場合:
# dec.py from time import time def add(x, y=10): before = time() rv = x + y after = time() print('time taken: ', after - before) return rv def sub(x, y=10): return x - y print('add(10)', add(10)) print('add(20, 30)', add(20, 30)) print('add("a", "b")', add("a", "b")) print('sub(10)', sub(10)) print('sub(20, 30)', sub(20, 30))
add と sub は両方とも関数であるため、これを利用してタイマー関数を作成できます。関数の操作時間を計算するタイマーが必要です:
def timer(func, x, y=10): before = time() rv = func(x, y) after = time() print('time taken: ', after - before) return rv
これは便利ですが、次のようにタイマー関数を使用してさまざまな関数をラップする必要があります:
print('add(10)', timer(add,10)))
デフォルト値はまだ 10 ですか?必ずしも。では、どうすればもっと良くなるでしょうか?
ここにアイデアがあります: 新しいタイマー関数を作成し、他の関数をラップし、ラップされた関数を返します:
def timer(func): def f(x, y=10): before = time() rv = func(x, y) after = time() print('time taken: ', after - before) return rv return f
あとは、add を timer And sub 関数でラップするだけです:
add = timer(add)
以上です!完全なコードは次のとおりです。
# dec.py from time import time def timer(func): def f(x, y=10): before = time() rv = func(x, y) after = time() print('time taken: ', after - before) return rv return f def add(x, y=10): return x + y add = timer(add) def sub(x, y=10): return x - y sub = timer(sub) print('add(10)', add(10)) print('add(20, 30)', add(20, 30)) print('add("a", "b")', add("a", "b")) print('sub(10)', sub(10)) print('sub(20, 30)', sub(20, 30)) Output: time taken:0.0 add(10) 20 time taken:9.5367431640625e-07 add(20, 30) 50 time taken:0.0 add("a", "b") ab time taken:9.5367431640625e-07 sub(10) 0 time taken:9.5367431640625e-07 sub(20, 30) -10
プロセスを要約しましょう。関数 (add 関数など) があり、その関数をアクション (タイミングなど) でラップします。パッケージ化の結果は、特定の新しい機能を実装できる新しい機能です。
もちろん、デフォルト値にはまだ問題があるため、後で修正します。
Decorator
さて、上記のソリューションはデコレータのアイデアに非常に近いものです。一般的な動作を使用して特定の関数をラップします。このパターンはデコレーションです。 . デバイスが何をしているのか。デコレータを使用した後のコードは次のとおりです。
def add(x, y=10): return x + y add = timer(add) You write: @timer def add(x, y=10): return x + y
これらの機能は同じであり、これは Python デコレータの機能です。実装する関数は add = timer(add) に似ていますが、デコレーターが構文を関数の上に置き、構文が @timer より単純である点が異なります。
# dec.py from time import time def timer(func): def f(x, y=10): before = time() rv = func(x, y) after = time() print('time taken: ', after - before) return rv return f @timer def add(x, y=10): return x + y @timer def sub(x, y=10): return x - y print('add(10)', add(10)) print('add(20, 30)', add(20, 30)) print('add("a", "b")', add("a", "b")) print('sub(10)', sub(10)) print('sub(20, 30)', sub(20, 30))
パラメータとキーワード パラメータ
ここで、解決されていない小さな問題がまだあります。タイマー関数では、パラメーター x と y をハードコーディングします。つまり、y のデフォルト値を 10 に指定します。引数とキーワード引数を関数に渡す方法 (*args と **kwargs) があります。パラメータは関数の標準パラメータ (この場合は x がパラメータ)、キーワード パラメータはすでにデフォルト値 (この場合は y=10) を持つパラメータです。コードは次のとおりです。
# dec.py from time import time def timer(func): def f(*args, **kwargs): before = time() rv = func(*args, **kwargs) after = time() print('time taken: ', after - before) return rv return f @timer def add(x, y=10): return x + y @timer def sub(x, y=10): return x - y print('add(10)', add(10)) print('add(20, 30)', add(20, 30)) print('add("a", "b")', add("a", "b")) print('sub(10)', sub(10)) print('sub(20, 30)', sub(20, 30))
これで、タイマー関数は、これらのパラメータを関数に渡すだけなので、任意の関数、任意のパラメータ、および任意のデフォルト値設定を処理できます。
高次デコレータ
関数を別の関数でラップして便利な動作を追加できれば、さらに一歩進められるのではないかと疑問に思うかもしれません。関数を別の関数でラップし、また別の関数によってラップされるのでしょうか? #########できる!実際、関数は必要に応じて深くすることができます。たとえば、関数を n 回実行するデコレーターを作成するとします。以下に示すように:
def ntimes(n): def inner(f): def wrapper(*args, **kwargs): for _ in range(n): rv = f(*args, **kwargs) return rv return wrapper return innerその後、上記の関数を使用して、前の記事の add 関数などの別の関数をラップできます:
@ntimes(3) def add(x, y): print(x + y) return x + y出力ステートメントは、コードが実際に実行されたことを示しています。 3回。
以上がPython デコレータを 1 つの記事で理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

Arraysinpython、特にvianumpy、arecrucialinscientificComputing fortheirefficienty andversitility.1)彼らは、fornumericaloperations、data analysis、andmachinelearning.2)numpy'simplementation incensuresfasteroperationsthanpasteroperations.3)arayableminablecickick

Pyenv、Venv、およびAnacondaを使用して、さまざまなPythonバージョンを管理できます。 1)Pyenvを使用して、複数のPythonバージョンを管理します。Pyenvをインストールし、グローバルバージョンとローカルバージョンを設定します。 2)VENVを使用して仮想環境を作成して、プロジェクトの依存関係を分離します。 3)Anacondaを使用して、データサイエンスプロジェクトでPythonバージョンを管理します。 4)システムレベルのタスク用にシステムPythonを保持します。これらのツールと戦略を通じて、Pythonのさまざまなバージョンを効果的に管理して、プロジェクトのスムーズな実行を確保できます。

numpyarrayshaveveraladvantages-averstandardpythonarrays:1)thealmuchfasterduetocベースのインプレンテーション、2)アレモレメモリ効率、特にlargedatasets、および3)それらは、拡散化された、構造化された形成術科療法、

パフォーマンスに対する配列の均一性の影響は二重です。1)均一性により、コンパイラはメモリアクセスを最適化し、パフォーマンスを改善できます。 2)しかし、タイプの多様性を制限し、それが非効率につながる可能性があります。要するに、適切なデータ構造を選択することが重要です。

craftexecutablepythonscripts、次のようになります

numpyarraysarasarebetterfornumeroperations andmulti-dimensionaldata、whilethearraymoduleissuitable forbasic、1)numpyexcelsinperformance and forlargedatasentassandcomplexoperations.2)thearraymuremememory-effictientivearientfa

NumPyArraySareBetterforHeavyNumericalComputing、whilethearrayarayismoreSuitableformemory-constrainedprojectswithsimpledatatypes.1)numpyarraysofferarays andatiledance andpeperancedatasandatassandcomplexoperations.2)thearraymoduleisuleiseightweightandmemememe-ef

ctypesallowsinging andmanipulatingc-stylearraysinpython.1)usectypestointerfacewithclibrariesforperformance.2)createc-stylearraysfornumericalcomputations.3)passarraystocfunctions foreffientientoperations.how、how、becuutiousmorymanagemation、performanceo


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境

MantisBT
Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

SublimeText3 中国語版
中国語版、とても使いやすい

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター

ホットトピック









