ホームページ > バックエンド開発 > Python チュートリアル > Python でのディープラーニングのクロージャ

Python でのディープラーニングのクロージャ

WBOY
リリース: 2016-06-16 08:42:13
オリジナル
1089 人が閲覧しました

クロージャは関数型プログラミングにおける重要な文法構造です。関数型プログラミングはプログラミング パラダイムです (手続き型プログラミングとオブジェクト指向プログラミングもプログラミング パラダイムです)。プロセス指向プログラミングでは関数を見てきましたが、オブジェクト指向プログラミングではオブジェクトを見てきました。関数とオブジェクトの基本的な目的は、コードを特定の論理的な方法で編成し、コードの再利用性を向上させることです。クロージャはコードを整理するための構造でもあり、コードの再利用性も向上します。

言語が異なれば、クロージャの実装方法も異なります。 Python は関数オブジェクトに基づいており、クロージャの構文構造のサポートを提供します (Python がオブジェクトを使用して、特殊なメソッドやマルチパラダイムで特殊な構文を実装していることを何度も見てきました)。 Python ではすべてがオブジェクトであり、関数の文法構造もオブジェクトです。関数オブジェクトでは、関数オブジェクトの名前を変更したり、関数オブジェクトをパラメータとして渡したりするなど、通常のオブジェクトと同じように関数オブジェクトを使用します。

関数オブジェクトのスコープ

他のオブジェクトと同様に、関数オブジェクトにも独自の生存範囲があり、それが関数オブジェクトのスコープです。関数オブジェクトは def ステートメントを使用して定義され、関数オブジェクトのスコープは def が配置されているレベルと同じです。たとえば、次のコードでは、line_conf 関数の所属スコープ内で定義した関数行は、line_conf の所属スコープ内でのみ呼び出すことができます。

コードをコピー コードは次のとおりです:

def line_conf():
定義行(x):
return 2*x+1
Print(line(5)) # スコープ内


line_conf()
print(line(5)) # 範囲外


line 関数は直線 (y = 2x + 1) を定義します。ご覧のとおり、line 関数は line_conf() で呼び出すことができますが、スコープ外で line を呼び出すと次のエラーが発生します:
コードをコピー コードは次のとおりです:

NameError: 名前「line」が定義されていません

現時点では対象外ということになります。

同様に、ラムダを使用して関数を定義する場合、関数オブジェクトのスコープはラムダが配置されているレベルと同じになります。

閉店

関数はオブジェクトなので、関数の戻り結果として使用できます。

コードをコピー コードは次のとおりです:

def line_conf():
定義行(x):
return 2*x+1
戻り行 # 関数オブジェクトを返します

my_line = line_conf()
print(my_line(5))

上記のコードは正常に実行できます。 line_confの戻り結果はlineオブジェクトに代入されます。上記のコードは 11 を出力します。

line() の定義で外部変数が参照された場合はどうなりますか?

コードをコピー コードは次のとおりです:

def line_conf():
b = 15
定義行(x):
return 2*x+b
戻り行 # 関数オブジェクトを返します

b = 5
my_line = line_conf()
print(my_line(5))


line で定義された下位プログラムブロック内で上位変数 b が参照されていますが、b の情報は line 定義の外に存在します(b の定義は line の下位プログラムブロック内にありません)。 b を line の環境変数と呼びます。実際、line を line_conf の戻り値として使用すると、line にはすでに b の値が含まれています (ただし、b は line に関連付けられていません)。

上記のコードは 25 を出力します。つまり、line で参照される b 値は、関数オブジェクトの定義時に参照できる b 値であり、使用時の b 値ではありません。

関数とその環境変数は一緒になってクロージャを形成します。 Python では、いわゆるクロージャは、環境変数の値を含む関数オブジェクトです。環境変数の値は、関数オブジェクトの __closure__ 属性に格納されます。たとえば、次のコード:

コードをコピー コードは次のとおりです:

def line_conf():
b = 15
定義行(x):
return 2*x+b
戻り行 # 関数オブジェクトを返します

b = 5
my_line = line_conf()
print(my_line.__closure__)
print(my_line.__closure__[0].cell_contents)

__closure__ にはタプルが含まれています。このタプルの各要素はセル型のオブジェクトです。最初のセルには整数 15 が含まれていることがわかります。これは、クロージャを作成したときの環境変数 b の値です。

クロージャの実際的な例を見てみましょう:

コードをコピー コードは次のとおりです:

def line_conf(a, b):
定義行(x):
return ax + b
戻り線

line1 = line_conf(1, 1)
line2 = line_conf(4, 5)
print(line1(5), line2(5))


この例では、関数行と環境変数 a および b がクロージャを形成します。クロージャを作成するとき、line_conf のパラメータ a と b を通じてこれら 2 つの環境変数の値を指定しました。このようにして、関数の最終形式 (y = x + 1 および y = 4x + 5) を決定しました。 。パラメータ a と b を変換するだけで、異なる直線式関数が得られます。このことから、クロージャにはコードの再利用性を向上させる効果もあることがわかります。

閉包がない場合、直線関数を作成するたびに a、b、x を指定する必要があります。この方法では、より多くのパラメーターを渡す必要があり、コードの移植性が低下します。クロージャを使用して、実際に関数を作成します。線関数は広義の関数を定義します。この関数の一部の側面はすでに決定されています (直線である必要があります) が、他の側面 (a および b パラメーターなど) は未決定です。続いて、line_conf によって渡されたパラメータに基づいて、クロージャの形式で最終関数を決定します。

クロージャと並列操作

クロージャは、関数が定義する必要があるパラメータの数を効果的に減らします。これは並列操作に重要な意味を持ちます。並列コンピューティング環境では、各コンピューターに機能を担当させ、あるコンピューターの出力を次のコンピューターの入力と連結できます。最終的には、一連のコンピューター クラスターの一方の端からデータを入力し、もう一方の端からデータを出力する、組み立てラインのように作業します。この状況は、パラメーター入力が 1 つだけの関数に最適です。クロージャはこの目的を達成できます。

並列コンピューティングがホットスポットになりつつあります。これは、関数型プログラミングが再び人気を集めている重要な理由でもあります。関数型プログラミングは 1950 年代には存在していましたが、あまり広く使用されていませんでした。ただし、上で説明したパイプライン化された作業並列クラスタリング プロセスは、関数型プログラミングに完全に適しています。関数型プログラミングの自然な利点により、ますます多くの言語が関数型プログラミング パラダイムのサポートを追加し始めています。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート