関数

関数 の Python

{other: "%{count}個の演習"}

関数について

functionは、特定のタスクを実行するために使われる、整理された再利用可能なコードのブロックです。 Functionsを使うと、アプリケーションのモジュール性が高まり、コードを高度に再利用できます。 Pythonには、ほかのプログラミング言語と同じように、すぐに使える組み込み関数(printやmapなど)があります。 自分で関数を定義することもでき、これはuser-defined functionsと呼ばれます。 関数は、_コンソールにメッセージを出力する_といった単純な処理から、とても複雑な処理まで実行できます。

関数の中にあるコードを実行するには、その関数を呼び出す必要があります。呼び出すには、関数名のあとに括弧(())を書きます。 argumentsと呼ばれるデータは、括弧の中に置くことで関数に渡せます。 関数の定義には、0個以上のparametersを含めることができます。 仮引数は、その関数がどのような引数を受け取るのかを定義します。 仮引数は、どの_型_の引数を渡すのかを定義します。 引数は、関数を呼び出すときに実際に渡される_値_です。 関数は、仮引数に渡される引数によって、さまざまな処理を行えます。

関数は、returnキーワードを使って値を返すこともできます。 関数が返す値は、return valueと呼ばれます。 戻り値は、関数を呼び出した側に返されます。

作成

Pythonでは、関数はdefキーワードを使って作成します。 関数の定義に続けて、関数名と括弧(())を書きます。 括弧の中には、コンマで区切って仮引数を指定します。 閉じ括弧のあとには、コロン(:)を書いて、関数のシグネチャと関数の本体を区切ります。

関数の本体は、関数が呼び出されたときに実行されるコードのブロックです。 関数の本体はインデントします。 インデントは重要です。Pythonはインデントによって、そのコードのブロックがどこで終わるのかを判断するからです。 returnキーワードを使うと、関数から値を返すことができ、その値は関数の呼び出し側で利用できます。

def function_name(parameter1, parameter2, ...):
    # function body
    return parameter1 + parameter2

仮引数も戻り値もない関数を定義することもできます。

def function_name():
    # function body
    pass

関数には本体が必要です。たとえ本体が何もしなくても、本体がないままプログラムを実行しようとすると、インデントエラーが発生します。

>>> def my_bodyless_func():
...      

File ~/temp.py:1
    
    ^
IndentationError: expected an indented block

関数の呼び出し

関数を呼び出すには、関数名のあとに括弧(())を書きます。 関数に渡す引数は、コンマで区切って括弧の中に置きます。

次の関数を見てみましょう。

def greet():
    print("Hello")

この関数は、次のように書いて呼び出せます。

>>> greet()
Hello

仮引数と引数

引数は、関数を呼び出すときにその関数へ渡される値です。 引数は、ほかの関数やクラスも含め、どんなデータ型でもかまいません。

2つの数値を足し合わせるaddという関数を定義してみましょう。

def add(first, second):
    print(first + second)

仮引数firstとsecondは、add関数がどのような引数を受け取るのかを定義します。 (parameterとargumentという言葉は、正確ではありませんが、しばしば同じ意味で使われることに注意してください。) 関数を呼び出すと、引数がその関数に渡されます。 2つの仮引数の両方に引数を渡す必要があります。そうでないと、TypeErrorが発生します。

>>> add(2, 3)
5

# Function can be called multiple times, with different parameters
>>> add(4, 3)
7
>>> add(5, 6)
11

# Passing an incorrect number of parameters will raise a `TypeError`
>>> add(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: add() missing 1 required positional argument: 'second'

>>> add(2, 3, 4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: add() takes 2 positional arguments but 3 were given

戻り値

戻り値は、関数を呼び出した側に返される値です。 return valueは、ほかの関数やクラスも含め、どんなデータ型でもかまいません。 戻り値は、関数の呼び出し側でさらに処理を行うために利用できます。 関数がreturn valueを明示的に定義していない場合、PythonのインタプリターはNoneという値を返します。

addという関数を定義してみましょう。

def add(first, second):
    return first + second

戻り値を変数に代入してから、それを出力できます。

>>> result = add(2, 3)
>>> print(result)
5
# Type of result is `int`
>>> type(result)
<class 'int'>

# We can also perform operations on the return value
>>> result * 2
10

# A function without an explicit return value will return `None`
>>> def log(message):
    print(message)

# Hello is printed because of print(message), but return value is `None`
>>> return_value = log("Hello")
Hello
>>> return_value
None

returnを使うと、その時点で関数を抜け、呼び出し側に値を返します。

>>> def show(first, second):
    print(first)
    return first
    print(second)

# second never gets printed, because the function exits after the return statement
>>> show(1, 2)
1

モジュール性

複雑なプログラムは、より小さな部分に分解できます。 それぞれ別の関数を使って、それぞれ異なる特定の処理を行えます。

あるプログラムが、次の処理を行う必要があるとします。

  • 円の面積を計算する
  • 長方形の面積を計算する
  • 三角形の面積を計算する

プログラムをより小さな部分に分解できます。

def circle_area(radius):
    return 3.14 * radius * radius

def rectangle_area(length, breadth):
    return length * breadth

def triangle_area(base, height):
    return 0.5 * base * height

これで、好きな順番で関数を呼び出せます。

>>> circle_area(2)
12.56
>>> triangle_area(2, 3)
3.0
>>> rectangle_area(2, 3)
6
>>> rectangle_area(1, 2) + circle_area(2) + triangle_area(1, 2)
15.56

変数のスコープ

関数の内側で定義された変数(または名前)は、関数の外側に同じ名前の変数があったとしても、関数のスコープ(またはローカル名前空間)の_内側_からしかアクセスできません。

関数の外側で_モジュールレベル_で定義された変数は、_グローバル名前空間_にあるとみなされます。 関数の外側だが、それを囲む関数やクラスの_内側_で定義された変数は、_ノンローカル名前空間_にあります。

Pythonは、プログラムの実行中に変数名を解決するために、LEGBルール(Local、Enclosing、Global、Built-in)を使います。

  1. local(または_関数_)名前空間を調べます。
  2. localで名前が見つからない場合は、enclosing(または_ノンローカル_)名前空間を調べます。
  3. nonlocal/enclosingで名前が見つからない場合は、global(モジュールレベル)名前空間を調べます。
  4. globalで名前が見つからない場合は、built-in(プログラム全体、またはPython全体)名前空間を調べます。

名前がそれでも解決できない場合、PythonはNameError exceptionを発生させます。

# Global namespace.
general_favorite = "apples"


def alices_favorite():
   # Local namespace.  
   favorite = "cherries"
   
   # This works because Python will eventually find general_favorite in the global namespace.
   # Python will find 'print' in the built-in namespace.
   print(f'Alice has always liked {favorite}, but most people like {general_favorite}.')

   
def our_favorite_fruits():
    # Enclosing or nonlocal namespace.
    yours = "peaches"
    
    def my_favorite():
        # Local namespace.
        mine = "pears"
        
        # This works because Python will eventually find 'yours' in the enclosing/nonlocal namespace.
        print(f'My favorite is {mine}, but you like {yours} instead.')
        
        # This works because Python will eventually find 'general_favorite' in the global namespace.
        print(f'Everyone seems to like {general_favorite}')
    
    # This function is in the local namespace of the 'our_favorite_fruits' function.  
    my_favorite()

    
# This will raise NameError: name 'favorite' is not defined, because the variable favorite is local to alices_favorite.
print(favorite)

変数名をローカルな関数スコープの_外側_からアクセスできるようにしたい場合(または、関数スコープの外側で定義された変数を変更したい場合)は、globalかnonlocalのキーワードを使う必要があります。

globalキーワードを使うと、Pythonは_グローバル名前空間_から名前の検索を始めます。 すると、その変数への代入は、_ローカル_な変数を作るのではなく、_グローバル_な変数を変更します。 globalを使って変数を宣言すると、その変数はグローバル名前空間に_追加_されます。 そのため、globalは慎重に使うべきです。グローバル変数を追加したり変更したりすると、その値を使うほかのすべてのコードに影響を与える可能性があるからです。

nonlocalキーワードは、_ノンローカル、またはそれを囲む名前空間_で変数を探す、または作成するようPythonに指示します。 これは、ある関数が別の関数やクラスの内側に入れ子になっていて、外側の関数の変数やスコープにアクセスする必要があるときに使います。

第一級オブジェクトとしての関数

Pythonでは、関数を変数に代入したり、ほかの関数の引数として渡したりできます。 戻り値として使うこともできます。 関数は、シーケンス(listやtupleなど)に入れたり、dictの値として使ったりもできます。 関数は、ほかのオブジェクトが使えるところならどこでも使えます。 これは、_関数が第一級オブジェクトである_ためです。 そのため、関数は特別な属性を持ち、さらに独自のカスタム属性の取得と設定を定義することもできます。

# print is a function

# A function can be assigned to a variable.
>>> function_as_variable = print
>>> function_as_variable("Hello")
Hello
>>> type(fake_print)
<class 'builtin_function_or_method'>

# Functions can be passed as an argument to another function.
>>> def check_print(func):
    func("Hello")
>>> check_print(print)
Hello

# Function can be used as an item in a sequence.
>>> my_list = [print, "Hello"]
>>> my_list[0]("Hello")
Hello

# Functions can be used as a value in a dictionary.
>>> my_dict = {"key": print}
>>> my_dict["key"]("Hello")
Hello

# Functions can be returned from a function.
>>> def return_func():
    return print
>>> return_func()("Hello")
Hello

関数は、ほかの関数の内側に入れ子にすることもできます。

def outer():
    num = 10
    
    # This is a nested, or "inner" function.
    def inner():
        print(num)
    
    # Outer function calling inner function
    inner()

内側の関数は、外側の関数で定義された変数numにアクセスできます。

>>> outer()
10

特別な属性

Pythonの関数には特別な属性があります。その一部を挙げます。

  • __name__:関数の名前
  • __doc__:関数のドキュメント文字列
  • __module__:その関数が定義されているモジュール
  • __globals__:その関数内のグローバル変数の辞書
  • __code__:関数の命令を含むコードオブジェクト
>>> def add(first, second):
      return first + second

# Function name
>>> print.__name__
'print'
>>> len.__name__
'len'
>>> add.__name__
'add'

# Function documentation
>>> abs.__doc__
'Return the absolute value of the argument.'

# Module
>>> len.__module__
'builtins'
>>> add.__module__
'__main__'

関数の属性の完全な一覧は、Pythonのデータモデルにあります。

GitHubで編集 リンクは新しいウィンドウまたはタブで開きます