ホームページ >バックエンド開発 >Python チュートリアル >Python 関数プログラミングについては、この記事を読んでください。

Python 関数プログラミングについては、この記事を読んでください。

PHPz
PHPz転載
2023-04-18 19:22:011516ブラウズ

Python 関数プログラミングについては、この記事を読んでください。

この記事では、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」で説明されているように:

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

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

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 キーワードを使用して定義された関数と同じように動作します。

注: ラムダ関数は 1 行である必要があり、プログラマが作成した return ステートメントを含めることはできません。

事实上,它们通常具备隐式的返回语句(在上面的示例中,函数想表达 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 的函数需要两个参数:一个表示正在接受检查的项,另一个表示所用运算的累积结果。

本文是关于函数式编程的一篇入门文章,虽然尽量完备地介绍了相关的知识,但并不是那么深入。如想了解更多,大家可以阅读以下资源:

  • Best Practices for Using Functional Programming in Python:https://kite.com/blog/python/functional-programming/
  • Functional Programming Tutorials and Notes:https://www.hackerearth.com/zh/practice/python/functional-programming/functional-programming-1/tutorial/

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

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