0から始めるPython独学ラボ

化学専門の大学生が趣味で始めたPythonをできるだけ分かりやすく説明します

イテレーターについて

今回はイテレーターについて取り扱っていきたいと思います。今までの記事ではたまに出てきたイテラブルなオブジェクトやイテレーションなどの用語が出てきましたよね。今回の記事では、この定義や概念について自分なりに説明していきたいと思います。

 

イテレーターとは、一言でいうとイテレーション可能なオブジェクトであり、イテレーションとは要素を一つずつ取り出すことができるオブジェクトです。

 

しかし、ここで注意してほしいのはイテラブルなオブジェクトとイテレーターは同一ではないということです。例えば、リストなどはイテラブルなオブジェクトではあるけれどイテレーターではなく、range関数で得られるのはイテレーターです。ちょっとややこしくなってきましたね。

 

for文はイテレーターを回すことができます。そして、リストやタプルなどもfor文で回すことができます。しかし、リストやタプルはあくまでイテラブルなオブジェクトであるけれどイテレーターではありません。しかし、for文を用いることができる以上イテレーターでなければいけません。つまり、リストやタプルなどはイテレーターを生成可能なオブジェクトであり、for文を実行するときにはイテレーターに変換されているのです。そのようなオブジェクトをイテラブルなオブジェクトと呼んでいます。なんとなく理解できたでしょうか?

 

リストなどのイテラブルなオブジェクトからイテレーターを取り出すにはiter()関数を使います。そして、イテレーターから値を一つずつ取り出すにはnext()関数を使います。実際に具体例を見ていきましょう。

 

テキストエディタ

nums = [1, 2, 3]
i = iter(nums)
print(next(i))
print(next(i))
print(next(i))

 

実行結果

1
2
3

iter関数の戻り値はイテレーターであるため、iはイテレーターになります。そして、イテレーターから値を一つずつイテレーションするためにnextが用いられています。

 

なんとなくイテレーターが理解できたでしょうか?

ここまでで今回の記事は終わりです。次は、自作のイテレーターを作成することができるジェネレーターについて取り扱います。

無名関数のfilterについて

今回の記事では、無名関数lambdaを用いたfilterの使い方を取り扱っていきます。前回の記事で取り扱ったmap関数と概ね同じです。mapはリストの全要素に処理を施すために使われますが、filterはリストから任意の要素を取り出すときに使われます。構文は以下のようになります。

 

filter(function, iterable)

 

filter関数の戻り値は、functionがTrueを返す要素だけで作成したものです。しかし、それはfilterオブジェクトなので、list関数に渡してリストに変換する必要があります。

 

以下は、リストのうち偶数のものだけを取り出して新しいリストを作るプログラムです。

 

テキストエディタ

nums = [1, 2, 3, 4]

nums2 = list(filter(lambda x : x%2 == 0, nums))
print(nums2)

 

実行結果

[2, 4]

 

このように、numsのうち x%2 == 0をみたす要素だけをfilter関数を用いると取り出すことができます。

 

以上で今回の記事は終わりです。お疲れさまでした。

無名関数のmapについて

今回は、無名関数lamdaを用いてリスト全ての値に対して処理を行うmap関数について取り扱っていきます。mapは以下の構文で使います。

 

map(function, iterable, ...)

 

functionには関数オブジェクトを使い、iterableにはリストやタプルなどの複数の値を持てるデータ型を渡します。第一引数の関数を第二引数のリストに適用し、結果を戻り値として返します。実際に具体例を見ていきましょう。

テキストエディタ

nums = [1, 2, 3, 4]

x1 = lambda x : x * 3

nums2 = list(map(x1, nums))

print(nums2)

 

実行結果

[3, 6, 9, 12]

 

このように、map関数を使えばリストの全ての値に対して処理を行うことができます。また、lamda関数を変数に代入せずに以下のように使うこともできます。

 

テキストエディタ

nums = [1, 2, 3, 4]

nums2 = list(map( lambda x : x * 3, nums))

print(nums2)

 

このように、書いたとしても同様の結果が得られます。

 

以上で今回の記事は終わりです。お疲れさまでした。

 

ローカル変数とグローバル変数について②

今回もローカルとグローバル変数、そしてスコープについて取り扱っていきます。

 

スコープには、LEGBルールがあります。これは、関数内で使用される変数がどのスコープに属するかを知るためのルールです。Lはローカルスコープ、Eは関数の外側の関数のスコープ、Gはグローバルスコープ、Bはビルトインスコープを表します。具体例を見ていきましょう。以下のコードがあるとします。

 

 

def a()

    return x

 

 

このようなコードが書かれたとき、もしもxが定義されていなければエラーが発生します。そのため、Pythonはxが定義されているのかどうか、さまざまなスコープを調べます。このスコープを調べる順番に、LEGBルールが存在します。優先順位はL E G Bの順番です。

 

この例において、まずPythonはxがローカルスコープで変数が定義されているかどうかを調べます。そして、ローカルスコープに存在しない場合には、Eスコープを調べます。Eスコープとは、関数内に関数がネストされている場合に存在する、内側の関数からみた外側の関数内に存在するスコープのことです。Eスコープに存在しない場合には、Gスコープを調べ、最後にBスコープを調べます。B(ビルトイン)スコープとは、Pythonの標準ライブラリの変数のことです。openとか、typeとかのことですね。

 

このようにしてPythonはスコープを調べていき、スコープ内に変数が見つかればその変数を使用します。そのスコープにを調べる優先順位がLEGBルールです。

 

 

 

以上で今回の記事は終わりです。お疲れ様でした。

ローカル変数とグローバル変数について

今回の記事では、関数のローカル変数とグローバル変数、またスコープの概念について取り扱っていきます。

python、もといプログラミングにはスコープというものが存在します。これが結構分かりにくくて、つまづきやすいところなので、今回は丁寧に取り扱っていきます。

 

スコープとは、ざっくりいうとプログラムの有効範囲を表す言葉です。例えばある変数xが定義されたときに、それが関数内で定義されたのか、関数外で定義されたのか異なるものになる、などという場合があります。関数内で変数xが定義された場合にはそのxの適用範囲は関数内のみであり、関数外で関数内で定義されたxを参照することができない、ということがあります。なんだかよく分からなくなってきたので、実際にコードを見ながら解説していきたいと思います。

 

テキストエディタ

x = 5

def a():

    x = 8

    return x

print(a())

print(x)

実行結果

8

5

 

この例のように、関数の中でxを定義し、そのxをreturnで返すと、戻り値として関数内で定義されたx(この例では8)が返され、関数外で定義されているxは返されません。しかし、関数を呼び出した後は関数内で定義されたx(これがいわゆるローカルスコープのx)は消滅し、関数外(これがいわゆるグローバルスコープ)で定義されたxのみが存在するため、print(x)によってグローバルスコープのxが参照されます。

 

なんとなくスコープについて理解できたでしょうか。最初に押さえておくべきスコープはローカルスコープとグローバルスコープの二つです。

 

ローカルスコープとは、関数内で定義した時に発生するスコープで、関数内で定義した変数はそのローカルスコープ内、つまりその関数内のみで有効であり、関数外では使うことができません。つまり、上記の例において

 

def a():

    x = 8

    return x

print(x)

と書くとエラーが発生します。なぜなら、変数Xは関数a()内のローカルスコープにのみ存在し、グローバルスコープでローカルスコープの変数にアクセスすることはできないからです。

 

 

グローバルスコープは、pyhtonプログラム全体で有効であり、グローバルスコープで定義した変数はグローバルスコープ、ローカルスコープの両方で有効です。つまり、上記の例で

 

x = 5

def a():

    return x

print(a())

と書くと、実行結果は

5

となります。つまり、この例では、ローカルスコープ(関数内)においてxが定義されていないため、グローバルスコープ(関数外)のxがreturn x のxに代入されたことになります。

 

ローカルスコープとグローバルスコープについてなんとなく理解できたでしょうか?

今回の記事はここまでで終わりです。次回もローカル変数とグローバル変数についてみていきます。お疲れさまでした。

もっと関数について③

今回は、関数の辞書型の可変長引数について取り扱っていきます。前回はタプル型でしたね。

 

辞書型の可変長引数は、アスタリスクを二回用いて**argsのように書きます。関数定義時に**argsと引数を指定した場合には、関数呼び出し時に 引数1= 引数2 のように書くと、{引数1:引数2}の辞書型の変数を作ることができます。コードとしては、

 

def a(**args):

    処理 

という風に関数を定義し、関数を呼び出すときは

a(x=30, y=40, z=50)

とすることで、関数内において変数argsに

{x:30, y:40, z:50}

という辞書型の値を作り出すことができます。また、関数を呼び出すときにはいくつでも引数を指定することができます。

 

以上のように、アスタリスクを一つ書くとタプル型の可変長引数を、アスタリスクを二つ書くと辞書型の可変長引数を書くことができます。

以上で今回の記事は終わりです。お疲れさまでした。

 

もっと関数について②

今回も関数について取り扱っていきます。

関数には引数が存在しますが、引数をいくつでも取ることができる方法が存在します。

それが可変長引数です。可変長なので、長さを自由に変化させることができるんですね。実際の引数との違いを見ていきましょう。以下のようなコードを書いたとします。

 

def a(x, y, z):

    return x + y + z

 

このようにコードを書けば、引数に指定した三つの数字を足し合わせることができます。しかし、この場合には引数は三つしか指定できません。任意の数を足し合わせる関数を書くことはできないのです。足し合わせる数が増えるたびに、関数を定義していくのは面倒ですよね。そこで、可変長引数を用います。可変長引数は、引数の前に * を付けるだけで完成するんですが、慣習として *args という風に書かれます。これはなぜかというと、こうすることでプログラムを読む人が、可変長引数であると見た瞬間に分かるからです。

 

可変長引数は、いつも引数の末尾に書きます。例えば

def a(x, y, *args):

    処理

と書き、これを呼び出すときに

a(1, 2, 3, 4, 5, 6)

と書いたならば、xに1が代入され、yに2が代入され、3、4、5、6はタプルとしてargsに代入されます。つまり、引数を呼び出すときに、宣言している引数以上の引数が指定された場合に、余剰の引数がすべてargsにタプルとして代入されるわけです。

 

具体例として、以下に全ての引数を足し合わせるプログラムを書いてみます。

 

テキストエディタ

def a(*args):

    y = 0

    for x in args:

        y +=x

    return y

print(a(1,2,3,4,5,6,7,8,9))

 

実行結果

45

 

この例では、関数の呼び出し時の引数全てがリストargsに代入され、そしてリストはイテラブル(繰り返し可能)なオブジェクトであるため、forにより中身を取り出して、それらを足し合わせています。

可変長引数について理解できたでしょうか?

今回はリスト型の可変長引数について取り扱いました。次は、辞書型の可変長引数について取り扱っていきましょう。

これで今回の記事は終わりです。お疲れさまでした。