python知識点-高次関数map、reduce、filter(3)
26955 ワード
1、反復可能なオブジェクトであれば、下付きの有無にかかわらず、dictのように反復できます.
dictの格納はlist方式で順番に並べられていないため,反復した結果の順序が異なる可能性が高い.
デフォルトではdict反復はkeyです.valueを反復する場合は
文字列も反復可能なオブジェクトであるため、
2、forサイクルの後にif判断を加えることもでき、偶数のみの二乗をスクリーニングすることができる:(注意:if条件はxのスクリーニング条件であり、x*xのスクリーニング条件ではない.)
リスト生成式は、listを生成するために2つの変数を使用することもできます.
3、関数名も変数
Pythonに内蔵されている絶対値を求める関数
しかし、もし
関数呼び出しの結果を取得するには、結果を変数に割り当てることができます.
しかし、関数自体を変数に割り当てるとしたら?
結論:関数自体も変数に値を割り当てることができます.すなわち、変数は関数を指すことができます.
変数が関数を指している場合、変数を使用して関数を呼び出すことができますか?コードで検証します.
成功!説明変数
4、高次関数
変数が関数を指すことができる以上、関数のパラメータは変数を受信することができ、1つの関数は別の関数をパラメータとして受信することができ、この関数は高次関数と呼ばれている.
最も簡単な高次関数:
コードで検証します.
高次関数を記述することは,関数のパラメータが他の関数を受信できるようにすることである.
5、Pythonには
では、Pythonコードで実現します.
確かにいいですが、上のループコードから、listの各要素にf(x)を作用させ、結果を新しいlistに生成することが一目でわかりますか?
したがって、
1行のコードしか必要ありません.
reduceの使い方を見てみましょう.reduceは1つの関数を1つのシーケンスに作用する[x 1,x 2,x 3...]で、この関数は2つのパラメータを受信する必要があります.reduceは結果をシーケンスの次の要素と累積計算し続けます.その効果は次のとおりです.
たとえば、1つのシーケンスの和を求めると、reduceで実現できます.
もちろん、求和演算はPython内蔵関数
しかし、シーケンス
この例自体はあまり役に立たないが、文字列
lambda関数をさらに簡略化することもできます.
つまり、Pythonが
Lambda関数の使い方は後述する.
6、
および
同様に、
関数とシーケンスも受信します.および
異なる場合、
たとえば、listで偶数を削除し、奇数だけを残します.
1つのシーケンスの空の文字列を削除するには、次のように書くことができます.
ソートアルゴリズム
ソートもプログラムでよく使われるアルゴリズムです.バブルソートを使用しても高速ソートを使用しても、ソートのコアは2つの要素のサイズを比較することです.数字なら直接比較できますが、文字列か2つのdictなら?数学の大きさを直接比較するのは意味がないので,比較の過程は関数によって抽象化しなければならない.通常、2つの要素
Pythonに内蔵されている
さらに、
カスタム比較関数
文字列のソートの例を見てみましょう.
デフォルトでは、文字列のソートは、ASCIIのサイズで比較されます.
次に、ソートは大文字と小文字を無視し、アルファベット順にソートすることを提案します.このアルゴリズムを実装するには、既存のコードを大きく変更する必要はありません.大文字と小文字を無視する比較アルゴリズムを定義できれば、次のことができます.
大文字と小文字を無視して2つの文字列を比較するのは、実際には文字列を大文字(または小文字)にしてから比較します.
これにより、
上記の例から,高次関数の抽象能力は非常に強く,コアコードは非常に簡潔に保つことができることが分かる.
>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> for key in d:
... print key
...
a
c
b
dictの格納はlist方式で順番に並べられていないため,反復した結果の順序が異なる可能性が高い.
デフォルトではdict反復はkeyです.valueを反復する場合は
for value in d.itervalues()
を使用し、keyとvalueを同時に反復する場合はfor k, v in d.iteritems()
を使用します.文字列も反復可能なオブジェクトであるため、
for
ループにも使用できます.>>> for ch in 'ABC':
... print ch
...
A
B
C
2、forサイクルの後にif判断を加えることもでき、偶数のみの二乗をスクリーニングすることができる:(注意:if条件はxのスクリーニング条件であり、x*xのスクリーニング条件ではない.)
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
リスト生成式は、listを生成するために2つの変数を使用することもできます.
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.iteritems()]
['y=B', 'x=A', 'z=C']
3、関数名も変数
Pythonに内蔵されている絶対値を求める関数
abs()
を例にとると、この関数を呼び出すには以下のコードが使用されます.>>> abs(-10)
10
しかし、もし
abs
しか書かなかったら?>>> abs
in function abs>
abs(-10)
は関数呼び出しであり、abs
は関数自体であることがわかる.関数呼び出しの結果を取得するには、結果を変数に割り当てることができます.
>>> x = abs(-10)
>>> x
10
しかし、関数自体を変数に割り当てるとしたら?
>>> f = abs
>>> f
in function abs>
結論:関数自体も変数に値を割り当てることができます.すなわち、変数は関数を指すことができます.
変数が関数を指している場合、変数を使用して関数を呼び出すことができますか?コードで検証します.
>>> f = abs
>>> f(-10)
10
成功!説明変数
f
は、abs
関数自体を指している.4、高次関数
変数が関数を指すことができる以上、関数のパラメータは変数を受信することができ、1つの関数は別の関数をパラメータとして受信することができ、この関数は高次関数と呼ばれている.
最も簡単な高次関数:
def add(x, y, f):
return f(x) + f(y)
add(-5, 6, abs)
を呼び出すと、パラメータx
,y
およびf
はそれぞれ-5
,6
およびabs
を受信し、関数定義に基づいて計算プロセスは次のように導出される.x ==> -5
y ==> 6
f ==> abs
f(x) + f(y) ==> abs(-5) + abs(6) ==> 11
コードで検証します.
>>> add(-5, 6, abs)
11
高次関数を記述することは,関数のパラメータが他の関数を受信できるようにすることである.
5、Pythonには
map()
とreduce()
関数が内蔵されている.高次関数では、Pythonコードで実現します.
>>> def f(x):
... return x * x
...
>>> map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
[1, 4, 9, 16, 25, 36, 49, 64, 81]
map()
入力された最初のパラメータは、f
であり、すなわち、関数オブジェクト自体である.map()
関数を必要とせず、ループを書いて結果を計算することもできます.L = []
for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]:
L.append(f(n))
print L
確かにいいですが、上のループコードから、listの各要素にf(x)を作用させ、結果を新しいlistに生成することが一目でわかりますか?
したがって、
map()
は高次関数として、実際には演算規則を抽象化しているので、簡単なf(x)=x 2を計算するだけでなく、任意の複雑な関数を計算することができます.例えば、このlistのすべての数字を文字列に変換することができます.>>> map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])
['1', '2', '3', '4', '5', '6', '7', '8', '9']
1行のコードしか必要ありません.
reduceの使い方を見てみましょう.reduceは1つの関数を1つのシーケンスに作用する[x 1,x 2,x 3...]で、この関数は2つのパラメータを受信する必要があります.reduceは結果をシーケンスの次の要素と累積計算し続けます.その効果は次のとおりです.
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
たとえば、1つのシーケンスの和を求めると、reduceで実現できます.
>>> def add(x, y):
... return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25
もちろん、求和演算はPython内蔵関数
sum()
を直接使用することができ、reduceを使用する必要はありません.しかし、シーケンス
[1, 3, 5, 7, 9]
を整数13579に変換するには、reduceが役立ちます.>>> def fn(x, y):
... return x * 10 + y
...
>>> reduce(fn, [1, 3, 5, 7, 9])
13579
この例自体はあまり役に立たないが、文字列
str
もシーケンスであることを考慮すると、上記の例を少し変更し、map()
に合わせると、str
をint
に変換する関数を書くことができる.>>> def fn(x, y):
... return x * 10 + y
...
>>> def char2num(s):
... return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
...
>>> reduce(fn, map(char2num, '13579'))
13579
str2int
に整理された関数は次のとおりです.def str2int(s):
def fn(x, y):
return x * 10 + y
def char2num(s):
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
return reduce(fn, map(char2num, s))
lambda関数をさらに簡略化することもできます.
def char2num(s):
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
def str2int(s):
return reduce(lambda x,y: x*10+y, map(char2num, s))
つまり、Pythonが
int()
関数を提供していないと仮定すると、文字列を整数に変換する関数を自分で書くことができ、数行のコードしか必要ありません.Lambda関数の使い方は後述する.
6、
および
map()
同様に、
filter()
関数とシーケンスも受信します.および
map()
異なる場合、
filter()
各要素に入力された関数を順次作用させ、戻り値がTrue
であるかFalse
であるかに基づいて、要素を保持または破棄するかを決定する.たとえば、listで偶数を削除し、奇数だけを残します.
def is_odd(n):
return n % 2 == 1
filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])
# : [1, 5, 9, 15]
1つのシーケンスの空の文字列を削除するには、次のように書くことができます.
def not_empty(s):
return s and s.strip()
filter(not_empty, ['A', '', 'B', None, 'C', ' '])
# : ['A', 'B', 'C']
filter()
という高次関数を用いることがわかり、重要なのは「フィルタ」関数を正しく実現することである.ソートアルゴリズム
ソートもプログラムでよく使われるアルゴリズムです.バブルソートを使用しても高速ソートを使用しても、ソートのコアは2つの要素のサイズを比較することです.数字なら直接比較できますが、文字列か2つのdictなら?数学の大きさを直接比較するのは意味がないので,比較の過程は関数によって抽象化しなければならない.通常、2つの要素
x
とy
について、x < y
と判断した場合は-1
を返し、x == y
と判断した場合は0
を返し、x > y
と判断した場合は1
を返し、これにより、ソートアルゴリズムは具体的な比較過程に関心を持たず、比較結果に基づいて直接ソートすることが規定されている.Pythonに内蔵されている
sorted()
関数はlistをソートできます.>>> sorted([36, 5, 12, 9, 21])
[5, 9, 12, 21, 36]
さらに、
sorted()
関数も高次関数であり、カスタムソートを実現するために比較関数を受信することもできる.たとえば、逆順序でソートする場合は、reversed_cmp
関数をカスタマイズできます.def reversed_cmp(x, y):
if x > y:
return -1
if x < y:
return 1
return 0
カスタム比較関数
reversed_cmp
を入力すると、逆順序ソートが可能になります.>>> sorted([36, 5, 12, 9, 21], reversed_cmp)
[36, 21, 12, 9, 5]
文字列のソートの例を見てみましょう.
>>> sorted(['bob', 'about', 'Zoo', 'Credit'])
['Credit', 'Zoo', 'about', 'bob']
デフォルトでは、文字列のソートは、ASCIIのサイズで比較されます.
'Z' < 'a'
の結果、大文字Z
は小文字a
の前に表示されます.次に、ソートは大文字と小文字を無視し、アルファベット順にソートすることを提案します.このアルゴリズムを実装するには、既存のコードを大きく変更する必要はありません.大文字と小文字を無視する比較アルゴリズムを定義できれば、次のことができます.
def cmp_ignore_case(s1, s2):
u1 = s1.upper()
u2 = s2.upper()
if u1 < u2:
return -1
if u1 > u2:
return 1
return 0
大文字と小文字を無視して2つの文字列を比較するのは、実際には文字列を大文字(または小文字)にしてから比較します.
これにより、
sorted
に上記の比較関数を入力すると、大文字と小文字を無視したソートが実現されます.>>> sorted(['bob', 'about', 'Zoo', 'Credit'], cmp_ignore_case)
['about', 'bob', 'Credit', 'Zoo']
上記の例から,高次関数の抽象能力は非常に強く,コアコードは非常に簡潔に保つことができることが分かる.