高度な閉鎖のpython [メモ]
ディレクトリ
クロージャの導入に問題に取り組むことでまず、次に閉鎖プロセス分析を解釈して実行します。
1.問題に
例えば、Y = KX + B、複数の点への線を計算する、すなわちxの値yの値を算出します。
# 问题:初中里学过函数,例如 y=kx+b, y=ax^2 + bx + c
# 以y=kx+b为例,请计算一条线上的多个点 即 给x值 计算出y值
# 第1种
# k = 1
# b = 2
# y = k*x+b
# 缺点:如果需要多次计算,那么就的写多次y = k*x+b这样的式子,不能重用
# 第2种:定义一个函数
def line_2(k, b, x):
print(k*x+b)
line_2(1, 2, 0)
line_2(1, 2, 1)
line_2(1, 2, 2)
# 缺点:如果想要计算多次这条线上的y值,那么每次都需要传递k,b的值,麻烦
print("-"*50)
# 第3种: 全局变量,
k = 1
b = 2
def line_3(x):
print(k*x+b)
line_3(0)
line_3(1)
line_3(2)
k = 11
b = 22
line_3(0)
line_3(1)
line_3(2)
# 缺点:如果要计算多条线上的y值,那么需要每次对全局变量进行修改,代码会增多,麻烦
print("-"*50)
# 第4种:缺省参数(注意,缺省参数放在后面)
def line_4(x, k=1, b=2):
print(k*x+b)
line_4(0)
line_4(1)
line_4(2)
line_4(0, k=11, b=22)
line_4(1, k=11, b=22)
line_4(2, k=11, b=22)
# 优点:比全局变量的方式好在:k, b是函数line_4的一部分 而不是全局变量,因为全局变量可以任意的被其他函数所修改
# 缺点:如果要计算多条线上的y值,那么需要在调用的时候进行传递参数,麻烦
print("-"*50)
# 第5种:实例对象
# 创建实例对象的时候设置好k和b
class Line5(object):
def __init__(self, k, b):
self.k = k
self.b = b
def __call__(self, x): # __call__方法,对象后面加括号,触发执行
print(self.k * x + self.b)
line_5_1 = Line5(1, 2)
# 对象.方法()
# 对象():会触发__call__方法
line_5_1(0) # 该形式即 对象() ,会调用__call__
line_5_1(1)
line_5_1(2)
line_5_2 = Line5(11, 22)
line_5_2(0)
line_5_2(1)
line_5_2(2)
# 缺点:为了计算多条线上的y值,所以需要保存多个k, b的值,因此用了很多个实例对象, 浪费资源
print("-"*50)
# 第6种:闭包
def line_6(k, b):
def create_y(x):
print(k*x+b)
return create_y
line_6_1 = line_6(1, 2) #
line_6_1(0)
line_6_1(1)
line_6_1(2)
line_6_2 = line_6(11, 22)
line_6_2(0)
line_6_2(1)
line_6_2(2)
第六に、ソリューションの閉鎖:
機能create_y変数kは、bがクロージャを構成しています。クロージャの作成では、我々はBショーこれら二つの変数の値は、パラメータk line_6を渡します。これは、最終形態(Y = KX + B)関数を決定します。私たちは、あなたが一次関数の異なる発現を得ることができ、パラメータK、Bを変更する必要があります。これを見ると、クロージャは、コードの再利用性を向上させるための役割を担っています。何クロージャがない場合、たび線形関数は、K、B、Xに記載の時間を作成する必要があります。複数のパラメータのためのコードの移植性を減らし、渡します。
(注:クロージャのためには、メモリを消費し、ローカル変数は、外部関数で放出されていない、ローカル変数、外部関数引用しました)
思考:関数、匿名関数、クロージャは、オブジェクトが引数が時に行う、違いは何ですか?
- 匿名関数は基本的な機能をシンプルに行うことができ、これは合格である関数への参照のみの機能(注:ラムダキーワードによって作成された匿名関数、コロンと表情一つだけを持っているが続きます)。
- より複雑な機能を完了するために通常の関数、送信された参照機能を機能のみ。
- 完全な、より複雑な機能にクロージャは、クロージャに送信される機能やデータ、従ってデータ転送機能である+(単純)。
- オブジェクトは、それが送信され、最も複雑な機能を完了するために大量のデータを多くの特徴+(プロパティとメソッドの数を使用することができる)ので、データ送信機能+です。
2.クロージャとは何ですか?(フォーカス)
内部関数次いで(機能多層ネストされた定義)関数を定義し、この関数は、外部変数の関数を使用し、この関数が使用され、そしていくつかの変数クロージャと呼ばれます。
# 定义一个函数
def test(number):
# 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
def test_in(number_in):
print("in test_in 函数, number_in is %d" % number_in)
return number+number_in
# 其实这里返回的就是闭包的结果
return test_in
# 给test函数赋值,这个20就是给参数number
ret = test(20)
# 注意这里的100其实给参数number_in
print(ret(100))
#注 意这里的200其实给参数number_in
print(ret(200))
実装プロセス:
- テスト= RET(20である):テスト機能を実行DEF test_inと 文はスキップ機能が定義され実行されない 、test_inとリターン 戻り参照機能と、
- RET この点関数でtest_inと 、実行RET(100) 関数呼び出し手段 test_inとを 、100の質量参加。
3.変更外部関数変数
クロージャはその関数の外の変数を変更する方法、グローバルローカル変数はグローバルキーワードで変更することができます修正しますか?
-
クロージャーは、非ローカル外部関数を使用して変数を変更します。
-
クロージャは、外部関数と同じ名前の変数に加え、非ローカル閉鎖を持っている場合は、外部変数の関数にアクセスできるようになります。
DEMO1
def counter(start=0): def incr(): nonlocal start start += 1 return start return incr c1 = counter(5) print(c1()) # 6 print(c1()) # 7 c2 = counter(50) print(c2()) # 51 print(c2()) # 52 print(c1()) # 8 print(c1()) # 9 print(c2()) # 53 print(c2()) # 54
DEMO2
x = 300 def test1(): x = 200 def test2(): nonlocal x # 因为下面定义了局部的x,不写这句的话下面的输出语句会一位x是局部变量的x,报错 print("----1----x=%d" % x) x = 100 print("----2----x=%d" % x) return test2 t1 = test1() t1()
出力:
---- ---- 1、X = 200
---- 2 ---- X = 100
注:上記のローカル以外の方法が適用とpython2ではありません。
- - -終わり - - -