Python プログラミング言語の優れた点の 1 つは、非常に便利なすべての機能が小さなパッケージに詰め込まれていることです。
多くの機能により Python コードの機能が完全に変更され、言語がさらに柔軟になります。これらの機能の一部を正しく使用すると、プログラムの作成に必要な時間を効果的に短縮できます。
これらの目標を達成する良い例は、Python のデコレータです。
デコレータは、Python 関数オブジェクトの動作を変更するために使用できる関数です。これらはクラスや関数に適用でき、本当に興味深いことがたくさんできます。
デコレータを使用すると、コードを短縮し、速度を上げ、Python でのコードの動作を完全に変えることができます。
言うまでもなく、これは確かに便利です。今日は、チェックする価値があると思うデコレーターをいくつか紹介したいと思います。
デコレータはたくさんありますが、最も優れた機能を備えていると思われるものをいくつか選びました。
このリストの最初のデコレータは functools モジュールからのものです。
このモジュールは標準ライブラリに含まれており、非常に使いやすいです。このデコレータよりも優れた機能も含まれていますが、このデコレータは間違いなく私のお気に入りです。
このデコレータを使用すると、キャッシュを使用して関数の連続実行を高速化できます。もちろん、これはキャッシュに関するいくつかの注意点を念頭に置いて使用する必要がありますが、一般的なユースケースでは、ほとんどの場合、このデコレータを使用する価値があります。
単純なデコレータを使用してコードを高速化できるのは素晴らしいことです。
このようなデコレータから恩恵を受ける可能性のある関数の良い例は、階乗を計算する関数などの再帰関数です。
def factorial(n): return n * factorial(n-1) if n else 1
再帰は、次の点で非常に困難になる可能性があります。計算時間は長くなりますが、このデコレータを追加すると、この関数の連続実行を大幅に高速化できます。
@lru_cache def factorial(n): return n * factorial(n-1) if n else 1
これで、この関数を実行するたびに、最初のいくつかの階乗計算がキャッシュに保存されます。
したがって、次回この関数を呼び出すときは、前に使用した階乗の後の階乗を計算するだけで済みます。
もちろん、すべての階乗計算が保存されるわけではありませんが、このデコレータが、自然に遅いコードを高速化するのに適したアプリケーションである理由は簡単にわかります。
JIT は Just In Time の略です。通常、Python でコードを実行すると、最初にコンパイルが行われます。
型にはメモリが割り当てられ、未割り当ての名前付きエイリアスとして保存されるため、このコンパイルではある程度のオーバーヘッドが発生します。ジャストインタイム コンパイルでは、実行時のみコンパイルします。
これは、多くの点で、Python インタープリターが時間を節約するために 2 つの処理を同時に処理する並列コンピューティングに似たものと考えることができます。
Numba JIT コンパイラーは、この概念を Python に導入したことで有名です。 @lru_cache と同様に、このデコレーターは非常に簡単に呼び出すことができ、コードのパフォーマンスを即座に向上させます。 Numba パッケージは、C を使用せずに、より負荷の高いソフトウェアを簡単に実行できるようにする jit デコレーターを提供します。
次のケースでは、@jit デコレータを使用してモンテカルロ法の計算を高速化します。
from numba import jit import random @jit(nopython=True) def monte_carlo_pi(nsamples): acc = 0 for i in range(nsamples): x = random.random() y = random.random() if (x ** 2 + y ** 2) < 1.0: acc += 1 return 4.0 * acc / nsamples
do_twice デコレーターの機能はその名前と似ています。このデコレータを使用すると、1 回の呼び出しで関数を 2 回実行できます。これには確かにいくつかの用途があり、特にデバッグに便利だと思います。
これは、2 つの異なる反復のパフォーマンスを測定するために使用できます。 Functools を例に挙げると、関数を 2 回実行して改善を確認できます。この関数は、標準ライブラリにある Python のデコレーター モジュールによって提供されます。
from decorators import do_twice @do_twice def timerfunc(): %timeit factorial(15)
count_calls デコレータを使用すると、ソフトウェア内で関数が使用された回数に関する情報を提供できます。
do_twice と同様、これはデバッグ時に確かに役立ちます。
特定の関数に追加すると、関数が実行されるたびに、その関数が何回実行されたかを示す出力を受け取ります。このデコレータは、標準ライブラリのデコレータ モジュールにも含まれています。
from decorators import count_calls @count_calls def function_example(): print("Hello World!") function_example() function_example() function_example()
クラスの作成時間を節約するために、私が常に使用してきた最高のデコレータの 1 つは @dataclass デコレータです。
このデコレータを使用すると、通常、作成するクラスに含まれる共通の標準メソッドをクラス内ですばやく作成できます。
このデコレータはデータクラス モジュールから取得されます。このモジュールは標準ライブラリにも含まれているため、この例を試すのに PIP は必要ありません。
from dataclasses import dataclass @dataclass class Food: name: str unit_price: float stock: int = 0 def stock_value(self) -> float: return(self.stock * self.unit_price)
このコードは、クラスにデータを設定するために必要な位置パラメータを持つ初期化関数 init() を自動的に作成します。
これらは self にも自動的に提供されるため、クラスにデータ パラメーターを入れるための長い関数を作成する必要はありません。
シングルトン デコレータの目的を理解するには、まずシングルトン (シングルトン) とは何かを理解する必要があります。ある意味、シングルトンはグローバル変数型のバージョンです。
这意味着类型被定义为只存在一次。尽管这些在 C++ 等语言中很常见,但在 Python 中却很少见到。使用单例,我们可以创建一个只使用一次的类并改变类,而不是通过初始化来构造新的类型。
通常,单例装饰器是由用户自己编写的,实际上并不是导入的。
这是因为单例仍然是对我们单例装饰器中提供的模板的引用。我们可以命名一个单例函数并编写一个包装器,以便在我们的类上使用这个装饰器:
def singleton(cls): instances = {} def wrapper(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return wrapper @singleton class cls: def func(self):
另一种方法是使用元类!
在科学计算中经常派上用场的一种装饰器是 @use_unit 装饰器。
此装饰器可用于更改返回结果的表示单位。这对于那些不想在数据中添加度量单位但仍希望人们知道这些单位是什么的人很有用。
这个装饰器也不是在任何模块中真正可用,但它是非常常见的,对科学应用程序非常有用。
def use_unit(unit): """Have a function return a Quantity with given unit""" use_unit.ureg = pint.UnitRegistry() def decorator_use_unit(func): @functools.wraps(func) def wrapper_use_unit(*args, **kwargs): value = func(*args, *_kwargs) return value _ use_unit.ureg(unit) return wrapper_use_unit return decorator_use_unit @use_unit("meters per second") def average_speed(distance, duration): return distance / duration
Functools 凭借非常有用的@singledispatch 装饰器再次在此列表中脱颖而出。
单调度是一种编程技术,在许多编程语言中都很常见,因为它是一种非常棒的编程方式。虽然我更喜欢多调度,但我认为单调度可以在很多方面扮演相同的角色。
这个装饰器使得在 Python 中使用多类型数据变得更加容易, 尤其当我们希望通过同一方法传递多种类型数据时,情况更是如此。
@singledispatch def fun(arg, verbose=False): if verbose: print("Let me just say,", end=" ") print(arg) @fun.register def _(arg: int, verbose=False): if verbose: print("Strength in numbers, eh?", end=" ") print(arg) @fun.register def _(arg: list, verbose=False): if verbose: print("Enumerate this:") for i, elem in enumerate(arg): print(i, elem)
以上が素晴らしい! 8 つのクールな Python デコレータをおすすめします。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。