原文:『実用的なPythonプログラミング』07_03_Returning_functions
5228 ワード
目次|前節(7.2匿名関数)|[次節(7.4デコレーション)]()
7.3戻り関数
このセクションでは、関数を使用して他の関数を作成する考え方について説明します.
概要
次の関数を考慮します.
これは他の関数を返す関数です.
ローカル変数
内部関数が外部関数で定義された変数をどのように参照するかを観察してください.
さらに観察すると、
クローズドパッケージ
内部関数が結果として返される場合、内部関数は閉パケット(closure)と呼ばれます.
≪基本プロパティ|Basic Properties|emdw≫:閉包は、関数が正常に動作した後に必要なすべての変数の値を保持します.閉パッケージは、依存する変数の値を保存するための追加の環境を持つ関数と見なすことができます.
クローズドパッケージの使用
閉パッケージはPythonの基本的な特性ですが、それらの使い方は通常微妙です.一般的なアプリケーション:はコールバック関数で使用されます. 遅延計算. アクセラレータ関数(後述).
ちえんけいさん
次のような関数を考慮します.
使用例:
閉パッケージには他の情報が付属しています.
コード繰返し
閉パケットは、コードの大量の重複を回避する技術としても使用することができる.
練習する
練習7.7:閉パッケージを使用して重複を避ける
閉パケットのより強力な特性は、重複するコードを生成することである.タイプチェック付きのプロパティを定義した練習5.7コードをレビューします.
コードを何度も入力するよりも、閉パッケージを使用して自動的にコードを作成します.
次に、次のようなクラスを定義してみましょう.
インスタンスを作成し、タイプチェックが有効かどうかを確認してください.
練習7.8:関数呼び出しの簡略化
上記の例では、ユーザは、
次に、
あ、少しよくなりました.ここでのポイントは、閉パッケージおよび
練習7.9:実践に移す
目次|前節(7.2匿名関数)|[次節(7.4デコレーション)]()
注:完全な翻訳はhttps://github.com/codists/practical-python-zhを参照
7.3戻り関数
このセクションでは、関数を使用して他の関数を作成する考え方について説明します.
概要
次の関数を考慮します.
def add(x, y):
def do_add():
print('Adding', x, y)
return x + y
return do_add
これは他の関数を返す関数です.
>>> a = add(3,4)
>>> a
>>> a()
Adding 3 4
7
ローカル変数
内部関数が外部関数で定義された変数をどのように参照するかを観察してください.
def add(x, y):
def do_add():
# `x` and `y` are defined above `add(x, y)`
print('Adding', x, y)
return x + y
return do_add
さらに観察すると、
add()
関数が終了した後も、これらの変数は生存していることが分かった.>>> a = add(3,4)
>>> a
>>> a()
Adding 3 4 # Where are these values coming from?
7
クローズドパッケージ
内部関数が結果として返される場合、内部関数は閉パケット(closure)と呼ばれます.
def add(x, y):
# `do_add` is a closure
def do_add():
print('Adding', x, y)
return x + y
return do_add
≪基本プロパティ|Basic Properties|emdw≫:閉包は、関数が正常に動作した後に必要なすべての変数の値を保持します.閉パッケージは、依存する変数の値を保存するための追加の環境を持つ関数と見なすことができます.
クローズドパッケージの使用
閉パッケージはPythonの基本的な特性ですが、それらの使い方は通常微妙です.一般的なアプリケーション:
ちえんけいさん
次のような関数を考慮します.
def after(seconds, func):
import time
time.sleep(seconds)
func()
使用例:
def greeting():
print('Hello Guido')
after(30, greeting)
after
(30秒遅延後)所定の関数を実行する......閉パッケージには他の情報が付属しています.
def add(x, y):
def do_add():
print(f'Adding {x} + {y} -> {x+y}')
return do_add
def after(seconds, func):
import time
time.sleep(seconds)
func()
after(30, add(2, 3))
# `do_add` has the references x -> 2 and y -> 3
コード繰返し
閉パケットは、コードの大量の重複を回避する技術としても使用することができる.
練習する
練習7.7:閉パッケージを使用して重複を避ける
閉パケットのより強力な特性は、重複するコードを生成することである.タイプチェック付きのプロパティを定義した練習5.7コードをレビューします.
class Stock:
def __init__(self, name, shares, price):
self.name = name
self.shares = shares
self.price = price
...
@property
def shares(self):
return self._shares
@shares.setter
def shares(self, value):
if not isinstance(value, int):
raise TypeError('Expected int')
self._shares = value
...
コードを何度も入力するよりも、閉パッケージを使用して自動的にコードを作成します.
typedproperty.py
ファイルを作成し、次のコードをファイルに入れてください.# typedproperty.py
def typedproperty(name, expected_type):
private_name = '_' + name
@property
def prop(self):
return getattr(self, private_name)
@prop.setter
def prop(self, value):
if not isinstance(value, expected_type):
raise TypeError(f'Expected {expected_type}')
setattr(self, private_name, value)
return prop
次に、次のようなクラスを定義してみましょう.
from typedproperty import typedproperty
class Stock:
name = typedproperty('name', str)
shares = typedproperty('shares', int)
price = typedproperty('price', float)
def __init__(self, name, shares, price):
self.name = name
self.shares = shares
self.price = price
インスタンスを作成し、タイプチェックが有効かどうかを確認してください.
>>> s = Stock('IBM', 50, 91.1)
>>> s.name
'IBM'
>>> s.shares = '100'
... should get a TypeError ...
>>>
練習7.8:関数呼び出しの簡略化
上記の例では、ユーザは、
typedproperty('shares', int)
のような呼び出しの方法が少し冗長であることを発見することができる(特に、複数回繰り返し呼び出した場合).次の定義をtypedproperty.py
ファイルに追加してください.String = lambda name: typedproperty(name, str)
Integer = lambda name: typedproperty(name, int)
Float = lambda name: typedproperty(name, float)
次に、
Stock
クラスを再記述して、次の関数を使用します.class Stock:
name = String('name')
shares = Integer('shares')
price = Float('price')
def __init__(self, name, shares, price):
self.name = name
self.shares = shares
self.price = price
あ、少しよくなりました.ここでのポイントは、閉パッケージおよび
lambda
がコードを簡略化し、嫌なコードの重複を解消するためによく使用されることです.これはいつもいいです.練習7.9:実践に移す
stock.py
ファイルのStock
クラスを再作成して、上記のタイプ化プロパティ(typed properties)を使用してください.目次|前節(7.2匿名関数)|[次節(7.4デコレーション)]()
注:完全な翻訳はhttps://github.com/codists/practical-python-zhを参照