ホームページ  >  記事  >  バックエンド開発  >  Python 関数プログラミング手法に関する詳細記事

Python 関数プログラミング手法に関する詳細記事

王林
王林転載
2023-04-13 15:16:071288ブラウズ

この記事では、Python の関数プログラミング テクノロジについて簡単に紹介します。

Python 関数プログラミング手法に関する詳細記事

第一級関数

Python では、関数は「第一級市民」です。つまり、関数は int などの他のデータ型と同等の立場にあります。

したがって、関数を変数に割り当て、それらを引数として他の関数に渡し、他のデータ構造 (辞書など) に格納し、他の関数の戻り値として使用することができます。

関数をオブジェクトとして扱う

他のデータ型 (string、list、int など) はオブジェクトであるため、Python では関数もオブジェクトです。独自の名前を出力する関数 foo の例を見てみましょう。

def foo():
 print("foo")

関数はオブジェクトであるため、関数 foo を任意の変数に割り当てて、その変数を呼び出すことができます。たとえば、変数 bar に関数を割り当てることができます。

bar = foo
bar()
#will print "foo" to the console

ステートメント bar = foo は、関数 foo によって参照されるオブジェクトを変数 bar に割り当てます。

オブジェクトを関数として扱う

オブジェクトが呼び出し可能な場合、オブジェクトは object() などの関数と同じになります。これは call メソッドを通じて実現されます。

例は次のとおりです:

class Greeter:
 def __init__(self, greeting):
self.greeting = greeting
 def __call__(self, name):
return self.greeting + " " + name

Greeter クラスのオブジェクトを構成するたびに、新しいオブジェクトを作成します。これは、挨拶するときに叫ぶことができる新しい名前です。以下に示すように:

morning = Greeter("good morning") #creates the callable object
morning("john") # calling the object
#prints "good morning john" to the console

朝のオブジェクトを呼び出すことができるのは、クラス定義で call メソッドを使用しているためです。オブジェクトが呼び出し可能かどうかを確認するには、組み込み関数 callable を使用します。

callable(morning) #true
callable(145) #false. int is not callable.

データ構造内の関数

関数は、他のオブジェクトと同様に、データ構造内に格納できます。たとえば、int から func までの辞書を作成できます。これは、int が実行されるステップの短縮表現である場合に便利です。

# store in dictionary
mapping = {
 0 : foo,
 1 : bar
}
x = input() #get integer value from user
mapping[x]() #call the func returned by dictionary access

同様に、関数は他のさまざまなデータ構造に格納できます。

関数をパラメータおよび戻り値として使用する

関数は、他の関数のパラメータおよび戻り値としても使用できます。関数を入力または返す関数として受け入れる関数は高階関数と呼ばれ、関数プログラミングの重要な部分です。

高階関数には強力な機能があります。 「Eloquent JavaScript」で説明されているように:

「高階関数を使用すると、抽象的な値だけでなく、アクションを抽象化できます。」

を見てみましょう。例。項目のリストを反復処理し、それらを順番に出力したいとします。反復関数は簡単に構築できます。

def iterate(list_of_items):
for item in list_of_items:
print(item)

これは見た目はクールですが、これは単なる第 1 レベルの抽象化です。リストを反復処理するときに印刷以外のことをしたい場合はどうすればよいでしょうか?

これが高階関数の存在の意味です。関数 iterate_custom を作成できます。この関数では、反復されるリストと各項目に適用される関数が iterate_custom 関数への入力となります。

def iterate_custom(list_of_items, custom_func):
 for item in list_of_items:
custom_func(item)

これは些細なことのように思えるかもしれませんが、実際には非常に強力です。

コードをより再利用しやすくするために、抽象化レベルを上げました。これで、リストを出力するときにこの関数を呼び出すことができるだけでなく、シーケンスの反復を含むリストに対して任意の操作を実行することもできます。

関数を返すこともできるので、さらに簡単になります。関数を dict に保存するのと同じように、関数を制御ステートメントとして使用して、適切な関数を決定することもできます。例:

def add(x, y):
return x + y
def sub(x, y):
return x - y
def mult(x, y):
return x * y
def calculator(opcode):
if opcode == 1:
 return add
elif opcode == 2:
 return sub
else:
 return mult 
my_calc = calculator(2) #my calc is a subtractor
my_calc(5, 4) #returns 5 - 4 = 1 
my_calc = calculator(9) #my calc is now a multiplier
my_calc(5, 4) #returns 5 x 4 = 20.

ネストされた関数

関数は他の関数の中に入れることもできます。これは「内部関数」です。組み込み関数は、メイン関数をサポートするサブモジュールとして機能する小さな再利用可能な関数であるヘルパー関数を作成する場合に役立ちます。

問題で特定の関数定義 (パラメーターの種類または順序) が必要な場合は、補助関数を使用できます。この非伝統的なアプローチにより、問題解決がはるかに簡単になります。例については、

http://www-inst.eecs.berkeley.edu/~cs61a/sp12/lectures/lect4-2x3.pdf を参照してください。

フィボナッチ関数 fib(n) を定義するとします。この関数にはパラメーター n が 1 つだけあり、n 番目のフィボナッチ数を返さなければなりません。

このような関数を定義する方法の 1 つは、ヘルパー関数を使用してフィボナッチ数列の最初の 2 つの項を追跡することです (フィボナッチ数は最初の 2 つの数値の合計であるため)。

def fib(n):
def fib_helper(fk1, fk, k):
if n == k:
 return fk
else:
 return fib_helper(fk, fk1+fk, k+1)
if n <= 1:
 return n
else:
 return fib_helper(0, 1, 1)

計算を関数本体から関数パラメーターに移動します。これは非常に強力です。再帰的メソッドで発生する可能性のある冗長な計算が削減されるためです。

単一式関数 (ラムダ式)

関数に名前を付ける前に関数を作成したい場合はどうすればよいでしょうか?短い 1 行の関数 (上記の例の関数 foo や mult など) を書きたい場合はどうすればよいでしょうか?

我们可以在 Python 中使用 lambda 关键字来定义此类函数。示例如下:

mult = lambda x, y: x * y
mult(1, 2) #returns 2

该 mult 函数的行为与使用传统 def 关键字定义函数的行为相同。

注意:lambda 函数必须为单行,且不能包含程序员写的返回语句。

事实上,它们通常具备隐式的返回语句(在上面的示例中,函数想表达 return x * y,不过我们省略了 lambda 函数中的显式返回语句)。

lambda 函数更加强大和精准,因为我们还可以构建匿名函数(即没有名称的函数):

(lambda x, y: x * y)(9, 10) #returns 90

当我们只需要一次性使用某函数时,这种方法非常方便。例如,当我们想填充字典时:

import collections
pre_fill = collections.defaultdict(lambda: (0, 0))
#all dictionary keys and values are set to 0

接下来我们来看 Map、Filter 和 Reduce,以更多地了解 lambda。

Map、Filter 和 Reduce

Map

map 函数基于指定过程(函数)将输入集转换为另一个集合。这类似于上文提到的 iterate_custom 函数。例如:

def multiply_by_four(x):
return x * 4
scores = [3, 6, 8, 3, 5, 7]
modified_scores = list(map(multiply_by_four, scores))
#modified scores is now [12, 24, 32, 12, 20, 28]

在 Python 3 中,map 函数返回的 map 对象可被类型转换为 list,以方便使用。现在,我们无需显式地定义 multiply_by_four 函数,而是定义 lambda 表达式:

modified_scores = list(map(lambda x: 4 * x, scores))

当我们想对集合内的所有值执行某项操作时,map 函数很有用。

Filter

就像名称所显示的那样,filter 函数可以帮助筛除不想要的项。例如,我们想要去除 scores 中的奇数,那么我们可以使用 filter:

even_scores = list(filter(lambda x: True if (x % 2 == 0) else False, scores))
#even_scores = [6, 8]

由于提供给 filter 的函数是逐个决定是否接受每一个项的,因此该函数必须返回 bool 值,且该函数必须是一元函数(即只使用一个输入参数)。

Reduce

reduce 函数用于「总结」或「概述」数据集。例如,如果我们想要计算所有分数的总和,就可以使用 reduce:

sum_scores = reduce((lambda x, y: x + y), scores)
#sum_scores = 32

这要比写循环语句简单多了。注意:提供给 reduce 的函数需要两个参数:一个表示正在接受检查的项,另一个表示所用运算的累积结果。

以上がPython 関数プログラミング手法に関する詳細記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事は51cto.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。