Python デコレータの詳細なサンプル チュートリアル
Python のデコレーターは、Python に入るハードルです。越えるか越えないかに関係なく、ハードルは存在します。 Python のデコレーターの概念は人々を混乱させることが多いので、今日は Python のデコレーターを分析しましょう
1 スコープ
Python には、グローバル スコープとローカル スコープの 2 種類のスコープがあります。
グローバル スコープは、ファイル レベルで定義された変数と関数の名前です。ローカル スコープは 定義関数 内にあります。
スコープに関しては、次の 2 つの点を理解する必要があります: a. ローカルに定義された変数はグローバルにアクセスできませんが、グローバルに定義された変数は変更できません (もちろん、変更する方法はあります)。
次の例を見てみましょう:x = 1 def funx(): x = 10 print(x) # 打印出10 funx() print(x) # 打印出1
定義された変数 x がローカルに存在しない場合、関数は x を内側から外側に検索します。それが見つからない場合は、エラーが報告されます。
x = 1 def funx(): print(x) # 打印出1 funx() print(x) # 打印出1 x = 1 def funx(): def func1(): print(x) # 打印出1 func1() funx() print(x) # 打印出1
2. 高度な関数
関数名は実際にはメモリ空間のアドレスを指していることがわかっているので、この機能を使用できます。 a.関数名を値として使用できますdef delete(ps): import os filename = ps[-1] delelemetns = ps[1] with open(filename, encoding='utf-8') as f_read,\ open('tmp.txt', 'w', encoding='utf-8') as f_write: for line in iter(f_read.readline, ''): if line != '\n': # 处理非空行 if delelemetns in line: line = line.replace(delelemetns,'') f_write.write(line) os.remove(filename) os.rename('tmp.txt',filename) def add(ps): filename = ps[-1] addelemetns = ps[1] with open(filename, 'a', encoding='utf-8') as fp: fp.write("\n", addelemetns) def modify(ps): import os filename = ps[-1] modify_elemetns = ps[1] with open(filename, encoding='utf-8') as f_read, \ open('tmp.txt', 'w', encoding='utf-8') as f_write: for line in iter(f_read.readline, ''): if line != '\n': # 处理非空行 if modify_elemetns in line: line = line.replace(modify_elemetns, '') f_write.write(line) os.remove(filename) os.rename('tmp.txt', filename) def search(cmd): filename = cmd[-1] pattern = cmd[1] with open(filename, 'r', encoding="utf-8") as f: for line in f: if pattern in line: print(line, end="") else: print("没有找到") dic_func ={'delete': delete, 'add': add, 'modify': modify, 'search': search} while True: inp = input("请输入您要进行的操作:").strip() if not inp: continue cmd_1 = inp.split() cmd = cmd_1[0] if cmd in dic_func: dic_func[cmd](cmd_1) else: print("Error")
def outer(): def inner(): pass return inner s = outer() print(s) ######输出结果为####### <function outer.<locals>.inner at 0x000000D22D8AB8C8>
def index(): print("index func") def outer(index): s = index s() outer(index) ######输出结果######### index func
3. クロージャ関数
クロージャ関数は、次の 2 つの条件を満たす必要があります。 1. 関数内で定義された関数 2.グローバル スコープではなく外部スコープが含まれます。 以下は、いくつかの例を通じてクロージャ関数への参照です: 例 1: 以下は関数内で関数を定義するだけですが、これはクロージャ関数ではありませんdef outer(): def inner(): print("inner func excuted") inner() # 调用执行inner()函数 print("outer func excuted") outer() # 调用执行outer函数 ####输出结果为########## inner func excuted outer func excuted
例2: 以下は関数 A 関数内で定義されており、外部変数も参照しています。 2 番目の項目が満たされていないことがわかったはずです。はい、ここでの変数 x はグローバル変数であり、外部に作用する変数ではありません。ドメイン。次の例を見てみましょう:
x = 1 def outer(): def inner(): print("x=%s" %x) # 引用了一个非inner函数内部的变量 print("inner func excuted") inner() # 执行inner函数 print("outer func excuted") outer() #####输出结果######## x=1 inner func excuted outer func excuted
明らかに、上記の例はクロージャー関数の条件を満たしています。ここで、クロージャ関数として、上記の 2 つの条件を満たさなければならず、どちらも削除できないことを知っておく必要があります。ただし、通常の状況では、クロージャ関数に値を返します。その理由についてはここでは説明しません。次のコンテンツで、この戻り値の使用方法を説明します。
def outer(): x = 1 def inner(): print("x=%s" %x) print("inner func excuted") inner() print("outer func excuted") outer() #####输出结果######### x=1 inner func excuted outer func excuted
次に、クロージャを定義します。関数。これは、関数とそれに関連する参照環境で構成されるエンティティです。深い制約を実装する場合、参照環境を明示的に表すものを作成し、それを関連するサブルーチンとバンドルして、バンドルがクロージャになるようにする必要があります。上記の例では、クロージャ関数が実際にクロージャ関数と呼ばれるには、それ自体の関数と外部変数が含まれている必要があることがわかります。外部変数がバインドされていない場合、関数はクロージャー関数とみなされません。
def outer(): x = 1 def inner(): print("x=%s" %x) print("inner func excuted") print("outer func excuted") return inner # 返回内部函数名 outer()
それでは、クロージャ関数が何をするのかは明らかです。 , クロージャー関数を定義する場合は、外部環境にバインドする必要があります。この全体をクロージャー関数とみなすことができ、このバインディング機能を使用して特定の特殊な関数を完成させることができます。
例3:受信したURLに従ってページのソースコードをダウンロードする
def outer(): x = 1 y = 2 def inner(): print("x= %s" %x) print("y= %s" %y) print(inner.closure) return inner outer() ######输出结果####### (<cell at 0x000000DF9EA965B8: int object at 0x000000006FC2B440>, <cell at 0x000000DF9EA965E8: int object at 0x000000006FC2B460>)
4. デコレータ
上記の基礎により、デコレータを簡単に理解できます。
デコレータ: 外部関数は装飾された関数の名前を渡し、内部関数は装飾された関数の名前を返します。
特徴: 1. 装飾された関数の呼び出しメソッドを変更しません 2. 装飾された関数のソースコードを変更しません a. パラメーターのないデコレーター
以下の例では、コードの実行時間を計算する必要があります。
import time, random def index(): time.sleep(random.randrange(1, 5)) print("welcome to index page")
根据装饰器的特点,我们不能对index()进行任何修改,而且调用方式也不能变。这时候,我们就可以使用装饰器来完成如上功能.
import time, random def outer(func): # 将index的地址传递给func def inner(): start_time = time.time() func() # fun = index 即func保存了外部index函数的地址 end_time = time.time() print("运行时间为%s"%(end_time - start_time)) return inner # 返回inner的地址 def index(): time.sleep(random.randrange(1, 5)) print("welcome to index page") index = outer(index) # 这里返回的是inner的地址,并重新赋值给index index()
但是,有些情况,被装饰的函数需要传递参数进去,有些函数又不需要参数,那么如何来处理这种变参数函数呢?下面来看看有参数装饰器的使用情况.
b.有参装饰器
def outer(func): # 将index的地址传递给func def inner(*args, **kwargs): start_time = time.time() func(*args, **kwargs) # fun = index 即func保存了外部index函数的地址 end_time = time.time() print("运行时间为%s"%(end_time - start_time)) return inner # 返回inner的地址
下面来说说一些其他情况的实例。
如果被装饰的函数有返回值
def timmer(func): def wrapper(*args,**kwargs): start_time = time.time() res=func(*args,**kwargs) #res来接收home函数的返回值 stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return res return wrapper def home(name): time.sleep(random.randrange(1,3)) print('welecome to %s HOME page' %name) return 123123123123123123123123123123123123123123
这里补充一点,加入我们要执行被装饰后的函数,那么应该是如下调用方式:
home = timmer(home) # 等式右边返回的是wrapper的内存地址,再将其赋值给home,这里的home不在是原来的的那个函数,而是被装饰以后的函数了。像home = timmer(home)这样的写法,python给我们提供了一个便捷的方式------语法糖@.以后我们再要在被装饰的函数之前写上@timmer,它的效果就和home = timmer(home)是一样的。
如果一个函数被多个装饰器装饰,那么执行顺序是怎样的。
import time import random def timmer(func): def wrapper(): start_time = time.time() func() stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return wrapper def auth(func): def deco(): name=input('name: ') password=input('password: ') if name == 'egon' and password == '123': print('login successful') func() #wrapper() else: print('login err') return deco @auth # index = auth(timmer(index)) @timmer # index = timmer(index) def index(): time.sleep(3) print('welecome to index page') index()
实验结果表明,多个装饰器装饰一个函数,其执行顺序是从下往上。
关于装饰器,还有一些高级用法,有兴趣的可以自己研究研究。
以上がPython デコレータの詳細なサンプル チュートリアルの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

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

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

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

ホットトピック











ほとんどのテキストエディターを使用して、XMLファイルを開きます。より直感的なツリーディスプレイが必要な場合は、酸素XMLエディターやXMLSPYなどのXMLエディターを使用できます。プログラムでXMLデータを処理する場合、プログラミング言語(Pythonなど)やXMLライブラリ(XML.ETREE.ELEMENTTREEなど)を使用して解析する必要があります。

モバイルには、単純で直接無料のXMLからPDFツールはありません。必要なデータ視覚化プロセスには、複雑なデータの理解とレンダリングが含まれ、市場のいわゆる「無料」ツールのほとんどは経験がありません。コンピューター側のツールを使用したり、クラウドサービスを使用したり、アプリを開発してより信頼性の高い変換効果を取得することをお勧めします。

XMLをPDFに直接変換するアプリケーションは、2つの根本的に異なる形式であるため、見つかりません。 XMLはデータの保存に使用され、PDFはドキュメントを表示するために使用されます。変換を完了するには、PythonやReportLabなどのプログラミング言語とライブラリを使用して、XMLデータを解析してPDFドキュメントを生成できます。

XMLコンテンツを変更するには、ターゲットノードの正確な検出が必要であるため、プログラミングが必要です。プログラミング言語には、XMLを処理するための対応するライブラリがあり、APIを提供して、データベースの運用などの安全で効率的で制御可能な操作を実行します。

XMLフォーマットツールは、読みやすさと理解を向上させるために、ルールに従ってコードを入力できます。ツールを選択するときは、カスタマイズ機能、特別な状況の処理、パフォーマンス、使いやすさに注意してください。一般的に使用されるツールタイプには、オンラインツール、IDEプラグイン、コマンドラインツールが含まれます。

XMLの美化は、合理的なインデンテーション、ラインブレーク、タグ組織など、本質的に読みやすさを向上させています。原則は、XMLツリーを通過し、レベルに応じてインデントを追加し、テキストを含む空のタグとタグを処理することです。 PythonのXML.ETREE.ELEMENTTREEライブラリは、上記の美化プロセスを実装できる便利なchile_xml()関数を提供します。

単一のアプリケーションで携帯電話でXMLからPDF変換を直接完了することは不可能です。クラウドサービスを使用する必要があります。クラウドサービスは、2つのステップで達成できます。1。XMLをクラウド内のPDFに変換し、2。携帯電話の変換されたPDFファイルにアクセスまたはダウンロードします。

携帯電話でXMLをPDFに直接変換するのは簡単ではありませんが、クラウドサービスの助けを借りて実現できます。軽量モバイルアプリを使用してXMLファイルをアップロードし、生成されたPDFを受信し、クラウドAPIで変換することをお勧めします。クラウドAPIはサーバーレスコンピューティングサービスを使用し、適切なプラットフォームを選択することが重要です。 XMLの解析とPDF生成を処理する際には、複雑さ、エラー処理、セキュリティ、および最適化戦略を考慮する必要があります。プロセス全体では、フロントエンドアプリとバックエンドAPIが連携する必要があり、さまざまなテクノロジーをある程度理解する必要があります。
