【Python】Python3.7.3-クローズド・クローズ・テクノロジー


文書ディレクトリ
  • Wikipedia対「一等関数」の定義
  • Wikipediaネスト関数の定義
  • Wikipedia対閉パッケージの定義
  • 閉パケットに対する理解
  • Pythonのネスト関数
  • Python閉パッケージの例
  • Python閉パッケージの実用例
  • 本稿では,閉パッケージ技術に対する自己の理解に基づいており,公式権威文書ではない.だから技術の間違いがあるかもしれません.伝言を歓迎します.
    まず準備活動をして、一等関数の定義を見てみましょう.
    Wikipediaの「一等関数」の定義
    In computer science, a programming language is said to have first-class functions if it treats functions as first-class citizens. This means the language supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures. Some programming language theorists require support for anonymous functions (function literals) as well. In languages with first-class functions, the names of functions do not have any special status; they are treated like ordinary variables with a function type. The term was coined by Christopher Strachey in the context of “functions as first-class citizens” in the mid-1960s.
    コンピュータ科学では、プログラム設計言語は「一等関数」と呼ばれ、その言語が関数を「一等公民」と見なす場合.これは,この言語がa)関数をパラメータとして他の関数に渡すことをサポートし,b)他の関数から関数を返すこと,c)関数を変数に付与したり,データ構造に格納したりすることを意味する.一部のプログラム設計言語理論学者は匿名関数(関数テキスト形式)のサポートも要求している.一等関数をサポートする言語では、関数名自体にステータスはありません.通常の変数として扱われますが、変数タイプは「関数」です.「一等関数/一等公民」という言葉はChristopher Stracheyが1960年代半ばの論文「functions as first-class citizens」で創造したものである.
    この定義から,C言語は一等関数を持つ言語であることが分かる.関数名、すなわち関数アドレス/ポインタにより、関数を他の関数に渡し、他の関数から関数アドレスを返し、関数ポインタを変数やデータ構造に保存することができます.
    同じように、Pythonも一等関数を持つ言語です.Pythonは匿名関数もサポートしています.
    一等関数があったら、誰が二等関数ですか.一部のプログラミング言語でサポートされているネスト関数は、プログラミング言語の二等公民と考えられる.
    Wikipediaのネスト関数の定義
    In computer programming, a nested function (or nested procedure or subroutine) is a function which is defined within another function, the enclosing function. Due to simple recursive scope rules, a nested function is itself invisible outside of its immediately enclosing function, but can see (access) all local objects (data, functions, types, etc.) of its immediately enclosing function as well as of any function(s) which, in turn, encloses that function. The nesting is theoretically possible to unlimited depth, although only a few levels are normally used in practical programs.
    プログラム設計言語では、ネスト関数(またはネストプロセス、またはサブルーチン)は、別の関数に定義された関数であり、外層のこの関数を含む関数(enclosing function)と呼ぶ.単純な再帰規則によれば、ネスト関数は、関数を含む外層関数以外の外層関数には表示されませんが、すべての外層関数のローカル変数にアクセスできます.このネストは原則として理論的に無線深さのネストをサポートすることができるが,実際の実装では少数の層のネストをサポートする.
    初期のALGOL、Simula 67、PASCAL、および現代の動的言語と関数式言語はネスト関数をサポートしていた.ただし、CおよびクラスCの言語ではネスト関数はサポートされていません.
    この定義から,ネスト関数は確かに二等公民であり,対外的にはほとんど見られず,他の関数を渡したり変数に保存したりすることは言うまでもない.
    しかし、時には、私たちは確かに内層関数を導出したり、いくつかの内層関数をカプセル化して使用したりする必要があります.この場合、どうすればいいですか.これには、パッケージテクノロジーをサポートする必要があります.
    Wikipediaの閉パッケージの定義
    https://en.wikipedia.org/wiki/Closure_(computer_programming)#History_and_etymology
    In programming languages, a closure, also lexical closure or function closure, is a technique for implementing lexically scoped name binding in a language with first-class functions. Operationally, a closure is a record storing a function together with an environment. The environment is a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created. Unlike a plain function, a closure allows the function to access those captured variables through the closure’s copies of their values or references, even when the function is invoked outside their scope.
    プログラム設計言語では、クローズドパッケージ(closure)とも呼ばれ、文法クローズドパッケージ(lexical closure)または関数クローズドパッケージ(function closure)とも呼ばれ、言語で「一等関数への文法範囲内の名前バインド」を実現するための技術である.実際の実装では、閉パケットは記録であり、関数と環境を格納します.環境は、閉パケットが作成されると、関数の各自由変数(free variable、ローカルで使用される変数ですが、閉じた範囲では定義されていません)を自由変数名表現の値または参照に関連付けます.単純な純粋な関数とは異なり、関数が定義範囲外で呼び出されても、値をコピーしたり参照したりすることで、関数が「取得された変数」にアクセスできます.
    閉パッケージの理解
  • 閉パッケージはプログラム設計技術
  • である.
  • 閉パケットは、命名バインドメカニズム
  • である.
  • 閉パケットは記録
  • である.
  • 閉パケットマッピング関係
  • を記録する
  • 閉パケットは、アクセスする非ローカル変数の値を記録するか、
  • を参照する.
  • は、記録された値または参照のコピー
  • が閉包.
  • 閉パケットは、定義ドメインの外で
  • にアクセスすることができる.
    Pythonのネスト関数
    1つの関数に定義された関数をネスト関数と呼びます.ネスト関数は、閉じた範囲(enclosing scope)内で定義された変数にアクセスできます.これは、Pythonでは、ネストされた関数が外層関数で定義された変数にアクセスできることを意味します.ネスト関数の場合、これらの変数はローカル変数ではなく、閉じた範囲内の変数を定義します.次の例を参照してください.
    #     :https://www.geeksforgeeks.org/python-closures/
    # Python program to illustrate 
    # nested functions 
    def outerFunction(text): 
    	# text   outerFunction     
    	text = text 
    
    	def innerFunction(): 
    		#       ,      text  
    		print(text) 
    
    	#       
    	innerFunction() 
    
    if __name__ == '__main__': 
    	outerFunction('Hey!') 
    

    Python閉パッケージの例
    Pythonの閉パッケージ技術では,ネストされた関数を外部世界に伝達したり,外部世界の関数をカプセル化したりして,新しい機能を追加することができる.
    #     :https://www.geeksforgeeks.org/python-closures/
    # Python program to illustrate 
    # closures 
    def outerFunction(text): 
    	text = text 
    
    	def innerFunction(): 
    		print(text) 
    
    	#       ,        
    	#   Python      ,         ;         
    	return innerFunction # Note we are returning function WITHOUT parenthesis 
    
    if __name__ == '__main__': 
    	#        outerFunction ,Python       
    	#    text   ,         
    	myFunction = outerFunction('Hey!') 
    	
    	#           ,InnerFunction      text   。
    	myFunction() 
    

    Python閉パッケージの実用例
    2つの関数add()とsub()があり、この2つの関数にログ機能を追加したいと考えています.クローズドパッケージ機能では、この2つの関数名をパラメータとしてlogger()に渡し、内層ネスト関数がログを印刷した後、渡された関数を実行/保存し、ネスト関数を返します.
    #     :https://www.geeksforgeeks.org/python-closures/
    # Python program to illustrate 
    # closures 
    import logging 
    logging.basicConfig(filename='example.log', level=logging.INFO) 
    
    
    def logger(func): 
    	#       
    	def log_func(*args): 
    		#     
    		logging.info( 
    			'Running "{}" with arguments {}'.format(func.__name__, args)) 
    		#   func,    
    		print(func(*args)) 
    	# Necessary for closure to work (returning WITHOUT parenthesis) 
    	return log_func			 
    
    #            
    def add(x, y): 
    	return x+y 
    
    def sub(x, y): 
    	return x-y 
    
    add_logger = logger(add) 
    sub_logger = logger(sub) 
    
    add_logger(3, 3) 
    add_logger(4, 5) 
    
    sub_logger(10, 5) 
    sub_logger(20, 10)