ホームページ バックエンド開発 Python チュートリアル Pythonでのクロージャ例の詳しい説明

Pythonでのクロージャ例の詳しい説明

Jun 16, 2016 am 08:42 AM
python 閉鎖

一般的に、クロージャの概念は多くの言語に関係しています。この記事では主に Python におけるクロージャの定義と関連する使用法について説明します。クロージャは主に Python で機能開発に使用されます。詳細な分析は次のとおりです:

1. 定義

Python のクロージャは、次のように表現的に定義 (解釈) されます。 内部関数で、外部スコープの変数 (グローバル スコープではない) が参照される場合、内部関数は相対的なクロージャとみなされます。他の定義ほど単純で理解しやすいです(これらの衒学的説明には、狂気を表すその他の馴染みのない用語がたくさんあり、初心者には適していません)。簡単な例を挙げて説明しましょう。

>>>def addx(x): 
>>> def adder(y): return x + y 
>>> return adder 
>>> c = addx(8) 
>>> type(c) 
<type 'function'> 
>>> c.__name__ 
'adder' 
>>> c(10) 
18

ログイン後にコピー

この単純なコードと定義を組み合わせて、クロージャを説明します。
内部関数内にある場合: adder(y) は内部関数です。
外部スコープ内の変数を参照します (ただし、グローバル スコープ内ではありません): x は参照される変数です。x は外部スコープ addx 内にありますが、グローバル スコープ内にはありません。
この内部関数加算器はクロージャです。

もう少し詳しく説明すると、関数を定義するときのクロージャ = 関数ブロック + 環境、adder が関数ブロック、x が環境であるということです。もちろん、単純な x だけではなく、多くの環境が存在する可能性があります。

2. クロージャを使用する際の注意点

1.外部スコープ内のローカル変数はクロージャ内で変更できません

>>> def foo(): 
...  m = 0 
...  def foo1(): 
...   m = 1 
...   print m 
... 
...  print m 
...  foo1() 
...  print m 
...
>>> foo()
0
1
0

ログイン後にコピー

実行結果からわかるように、クロージャ内でも変数mが定義されていますが、外部関数内のローカル変数mは変更されません。

2. 次のコードは、Python でクロージャを使用する場合の典型的なエラー コードです

def foo(): 
 a = 1 
 def bar(): 
  a = a + 1 
  return a 
 return bar

ログイン後にコピー

このプログラムの本来の目的は、クロージャー関数が呼び出されるたびに変数 a をインクリメントすることです。しかし、実際に使用する場合

>>> c = foo() 
>>> print c() 
Traceback (most recent call last): 
 File "<stdin>", line 1, in <module> 
 File "<stdin>", line 4, in bar 
UnboundLocalError: local variable 'a' referenced before assignment 

ログイン後にコピー

これは、コード c = foo() を実行するときに、Python がローカル変数を分析するためにすべてのクロージャ関数本体 bar() をインポートするためです。代入ステートメントの左側のすべての変数はローカル変数であると Python ルールで指定されています。次に、クロージャ bar() では、変数 a が代入記号「=」の左側にあり、Python によって bar() のローカル変数とみなされます。次に print c() が実行されると、プログラムは a = a + 1 まで実行されます。 a は事前に bar() のローカル変数として分類されているため、Python は bar の代入ステートメントの右側にある変数を探します。 ()。 a の値が見つからない場合は、エラーが報告されます。解決策は簡単です

def foo(): 
 a = [1] 
 def bar(): 
  a[0] = a[0] + 1 
  return a[0] 
 return bar

ログイン後にコピー

a をコンテナとして設定するだけです。これは使用するのがやや不快なので、python3 以降、a = a + 1 の前に非ローカル a ステートメントを使用するだけです。このステートメントは、a がクロージャのローカル変数ではないことを明示的に指定します。

3. Python クロージャを導入するときによく取り上げられる、エラーが発生しやすい例があります。このエラーがクロージャとあまり関係があるとは考えたこともありませんでしたが、確かに Python 関数のプログラミングは簡単です。間違えやすいのでここで紹介しておきます。以下のコードを見てみましょう

for i in range(3): 
 print i

ログイン後にコピー

このようなループ文はプログラムによく登場します。Python の問題は、ループが終了しても、ループ本体内の一時変数 i が破棄されず、実行環境に存在し続けることです。もう 1 つの Python 現象は、Python 関数は実行時に関数本体内の変数の値しか見つけられないことです。

flist = [] 
for i in range(3): 
 def foo(x): print x + i 
 flist.append(foo) 
for f in flist: 
 f(2)

ログイン後にコピー

このコードの実行結果は 2,3,4 になるはずだと思う人もいるかもしれませんが、実際の結果は 4,4,4 です。これは、関数が flist リストに追加されるとき、Python は i に値を割り当てていないためです。このとき、最初の for ループが終了した後でのみ、i の値が見つかります。 i は 2 です。つまり、上記のコードの実行結果は 4,4,4.
となります。 解決策も非常に簡単で、関数の定義を書き換えるだけです。

for i in range(3): 
 def foo(x,y=i): print x + y 
 flist.append(foo) 

ログイン後にコピー

3. 機能

ここまで述べたので、実際の開発においてこのクロージャは何に役立つのかと疑問に思う人もいるかもしれません。クロージャは主に機能開発中に使用されます。以下に 2 つのクロージャの主な用途について説明します。

目的 1: クロージャ実行後も、現在の動作環境を維持できます。

たとえば、関数の各実行の結果を、この関数の最後の実行の結果に基づくようにしたい場合。ボードゲームに似た例で説明しましょう。チェス盤のサイズが 50*50 で、左上隅が座標系の原点 (0,0) であると仮定します。この関数は、方向とステップの 2 つのパラメーターを受け取る関数が必要です。チェスの駒。方向とステップの長さに加えて、チェスの駒の動きの新しい座標も元の座標点に依存します。クロージャを使用して、チェスの駒の元の座標を維持することができます。

origin = [0, 0] # 坐标系统原点 
legal_x = [0, 50] # x轴方向的合法坐标 
legal_y = [0, 50] # y轴方向的合法坐标 
def create(pos=origin): 
 def player(direction,step): 
  # 这里应该首先判断参数direction,step的合法性,比如direction不能斜着走,step不能为负等 
  # 然后还要对新生成的x,y坐标的合法性进行判断处理,这里主要是想介绍闭包,就不详细写了。 
  new_x = pos[0] + direction[0]*step 
  new_y = pos[1] + direction[1]*step 
  pos[0] = new_x 
  pos[1] = new_y 
  #注意!此处不能写成 pos = [new_x, new_y],原因在上文有说过 
  return pos 
 return player 
 
player = create() # 创建棋子player,起点为原点 
print player([1,0],10) # 向x轴正方向移动10步 
print player([0,1],20) # 向y轴正方向移动20步 
print player([-1,0],10) # 向x轴负方向移动10步 

ログイン後にコピー

出力は次のとおりです:

[10, 0] 
[10, 20] 
[0, 20] 

ログイン後にコピー

用途2:闭包可以根据外部作用域的局部变量来得到不同的结果,这有点像一种类似配置功能的作用,我们可以修改外部的变量,闭包根据这个变量展现出不同的功能。比如有时我们需要对某些文件的特殊行进行分析,先要提取出这些特殊行。

def make_filter(keep): 
 def the_filter(file_name): 
  file = open(file_name) 
  lines = file.readlines() 
  file.close() 
  filter_doc = [i for i in lines if keep in i] 
  return filter_doc 
 return the_filter

ログイン後にコピー

如果我们需要取得文件"result.txt"中含有"pass"关键字的行,则可以这样使用例子程序

filter = make_filter("pass")
filter_result = filter("result.txt")

ログイン後にコピー

以上两种使用场景,用面向对象也是可以很简单的实现的,但是在用Python进行函数式编程时,闭包对数据的持久化以及按配置产生不同的功能,是很有帮助的。

相信本文所述对大家的Python程序设计有一定的借鉴价值。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Debian Apacheログを使用してWebサイトのパフォーマンスを向上させる方法 Debian Apacheログを使用してWebサイトのパフォーマンスを向上させる方法 Apr 12, 2025 pm 11:36 PM

この記事では、Debianシステムの下でApacheログを分析することにより、Webサイトのパフォーマンスを改善する方法について説明します。 1.ログ分析の基本Apacheログは、IPアドレス、タイムスタンプ、リクエストURL、HTTPメソッド、応答コードなど、すべてのHTTP要求の詳細情報を記録します。 Debian Systemsでは、これらのログは通常、/var/log/apache2/access.logおよび/var/log/apache2/error.logディレクトリにあります。ログ構造を理解することは、効果的な分析の最初のステップです。 2。ログ分析ツールさまざまなツールを使用してApacheログを分析できます。コマンドラインツール:GREP、AWK、SED、およびその他のコマンドラインツール。

Python:ゲーム、GUIなど Python:ゲーム、GUIなど Apr 13, 2025 am 12:14 AM

PythonはゲームとGUI開発に優れています。 1)ゲーム開発は、2Dゲームの作成に適した図面、オーディオ、その他の機能を提供し、Pygameを使用します。 2)GUI開発は、TKINTERまたはPYQTを選択できます。 TKINTERはシンプルで使いやすく、PYQTは豊富な機能を備えており、専門能力開発に適しています。

PHPとPython:2つの一般的なプログラミング言語を比較します PHPとPython:2つの一般的なプログラミング言語を比較します Apr 14, 2025 am 12:13 AM

PHPとPythonにはそれぞれ独自の利点があり、プロジェクトの要件に従って選択します。 1.PHPは、特にWebサイトの迅速な開発とメンテナンスに適しています。 2。Pythonは、データサイエンス、機械学習、人工知能に適しており、簡潔な構文を備えており、初心者に適しています。

DDOS攻撃検出におけるDebianスニファーの役割 DDOS攻撃検出におけるDebianスニファーの役割 Apr 12, 2025 pm 10:42 PM

この記事では、DDOS攻撃検出方法について説明します。 「DebiansNiffer」の直接的なアプリケーションのケースは見つかりませんでしたが、次の方法はDDOS攻撃検出に使用できます:効果的なDDOS攻撃検出技術:トラフィック分析に基づく検出:突然のトラフィックの成長、特定のポートの接続の急増などのネットワークトラフィックの異常なパターンの識別。たとえば、PysharkライブラリとColoramaライブラリと組み合わせたPythonスクリプトは、ネットワークトラフィックをリアルタイムで監視し、アラートを発行できます。統計分析に基づく検出:データなどのネットワークトラフィックの統計的特性を分析することにより

Nginx SSL証明書更新Debianチュートリアル Nginx SSL証明書更新Debianチュートリアル Apr 13, 2025 am 07:21 AM

この記事では、DebianシステムでNGINXSSL証明書を更新する方法について説明します。ステップ1:最初にCERTBOTをインストールして、システムがCERTBOTおよびPython3-Certbot-Nginxパッケージがインストールされていることを確認してください。インストールされていない場合は、次のコマンドを実行してください。sudoapt-getupdatesudoapt-getinstolcallcertbotthon3-certbot-nginxステップ2:certbotコマンドを取得して構成してlet'sencrypt証明書を取得し、let'sencryptコマンドを取得し、nginx:sudocertbot - nginxを構成します。

Debian Readdirが他のツールと統合する方法 Debian Readdirが他のツールと統合する方法 Apr 13, 2025 am 09:42 AM

DebianシステムのReadDir関数は、ディレクトリコンテンツの読み取りに使用されるシステムコールであり、Cプログラミングでよく使用されます。この記事では、ReadDirを他のツールと統合して機能を強化する方法について説明します。方法1:C言語プログラムを最初にパイプラインと組み合わせて、cプログラムを作成してreaddir関数を呼び出して結果をinclude#include#include inctargc、char*argv []){dir*dir; structdireant*entry; if(argc!= 2){(argc!= 2){

Pythonと時間:勉強時間を最大限に活用する Pythonと時間:勉強時間を最大限に活用する Apr 14, 2025 am 12:02 AM

限られた時間でPythonの学習効率を最大化するには、PythonのDateTime、時間、およびスケジュールモジュールを使用できます。 1. DateTimeモジュールは、学習時間を記録および計画するために使用されます。 2。時間モジュールは、勉強と休息の時間を設定するのに役立ちます。 3.スケジュールモジュールは、毎週の学習タスクを自動的に配置します。

debian opensslでHTTPSサーバーを構成する方法 debian opensslでHTTPSサーバーを構成する方法 Apr 13, 2025 am 11:03 AM

DebianシステムでHTTPSサーバーの構成には、必要なソフトウェアのインストール、SSL証明書の生成、SSL証明書を使用するWebサーバー(ApacheやNginxなど)の構成など、いくつかのステップが含まれます。 Apachewebサーバーを使用していると仮定して、基本的なガイドです。 1.最初に必要なソフトウェアをインストールし、システムが最新であることを確認し、ApacheとOpenSSL:sudoaptupdatesudoaptupgraysudoaptinstaをインストールしてください

See all articles