Lesson 4

データ構造

Lesson 4 Chapter 1
リスト型で使用する代表的な関数

「pop」や「remove」を用いたリストの操作を、Lesson2のChapter5で学びましたが、それ以外にも使用可能な関数がPythonには標準機能として用意してあります。このChapterでは、「pop」や「remove」のようにリスト型と合わせて使用すると便利な関数について解説していきます。

リストの要素全てを削除するclear関数

リスト内の全ての要素を削除するには、以下のようにclear関数を使用します。

clear_test.py
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9]

print('clear前:' , lst)

lst.clear()

print('clear後:' , lst)

出力結果

clear前: [1, 2, 3, 4, 5, 6, 7, 8, 9]
clear後: []

文字列を連結するjoin関数

join関数を使用して、リスト内の要素を連結することが可能です。以下のコードでは、2つの要素を、空白で連結した場合と&で連結した場合のパターンを記述しています。

join_test.py
lst = ['Good', 'Morning']

print('join前:' ,lst)

lst2 = ' '.join(lst)
lst3 = '&'.join(lst)

print('join後:' , lst2)
print('join後:' , lst3)

出力結果

join前: ['Good', 'Morning']
join後: Good Morning
join後: Good&Morning

要素の重複を取り除くset関数

リスト内に重複した要素が存在した場合、取り除くことが可能です。

set_test.py
lst = [9, 1, 2, 3, 4, 5, 5, 6, 7, 6, 8, 9]

print('set前:' , lst)

lst2 = set(lst)

print('set後:' , lst2)

出力結果

set前: [9, 1, 2, 3, 4, 5, 5, 6, 7, 6, 8, 9]
set後: {1, 2, 3, 4, 5, 6, 7, 8, 9}

重複の削除に加えて、要素が並び替えられていることも確認できます。

要素の出現回数をカウントするcount関数

リスト内の要素をカウントするには、count関数を使用します。重複した要素も含めてカウントが可能です。

count_test.py
lst = ['田中', '佐藤', '鈴木', '山本', '吉田', '佐藤', '田中', '佐藤', '小林', '佐藤']

count1 = lst.count('田中')
count2 = lst.count('佐藤')
count3 = lst.count('鈴木')

print('田中:' , count1, '人')
print('佐藤:' , count2, '人')
print('鈴木:' , count3, '人')

出力結果

田中: 2 人
佐藤: 4 人
鈴木: 1 人

要素を昇順に並び替えるsort関数

sort関数は、要素を昇順に並べ替えることが可能です。

sort_test.py
lst = [5,8,7,9,1,2,4,10,3,6]

print('sort前:' , lst)

lst.sort()

print('sort後:' , lst)

出力結果

sort前: [5, 8, 7, 9, 1, 2, 4, 10, 3, 6]
sort後: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

降順に並び替えるには、以下のコードのように、引数に「reverse=True」を指定します。

sort_test.py
lst = [5,8,7,9,1,2,4,10,3,6]

print('sort前:' , lst)

lst.sort(reverse=True)

print('sort後:' , lst)

出力結果

sort前: [5, 8, 7, 9, 1, 2, 4, 10, 3, 6]
sort後: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

文字列の並び替えも可能です。

sort2_test.py
lst = ['morning','afternoon','evening','night']

print('sort前:' , lst)

lst.sort()

print('sort後:' , lst)

出力結果

sort前: ['morning', 'afternoon', 'evening', 'night']
sort後: ['afternoon', 'evening', 'morning', 'night']

アルファベット順に並び変えられました。

要素を逆順に並び替えるreverse関数

reverse関数は、要素を逆順に並び替えることが可能です。

reverse_test.py
lst = [5,8,7,9,1,2,4,10,3,6]

print('reverse前:' , lst)

lst.reverse()

print('reverse後:' , lst)

出力結果

reverse前: [5, 8, 7, 9, 1, 2, 4, 10, 3, 6]
reverse後: [6, 3, 10, 4, 2, 1, 9, 7, 8, 5]

降順に並び替えるのではなく、定義された要素の並びを逆順にしていることに注意してください。

要素のインデックス番号を調べるindex関数

index関数を使用して要素のインデックス番号を調べることで、要素の位置が明らかになります。

index_test.py
lst = ['Tokyo', 'Osaka', 'Nagoya', 'Sapporo']

index1 = lst.index('Tokyo')
index2 = lst.index('Sapporo')

print('東京のインデックス番号:' , index1)
print('札幌のインデックス番号:' , index2)

出力結果

東京のインデックス番号: 0
札幌のインデックス番号: 3

Lesson 4 Chapter 2
リストの内包表記

Lesson2でif文やfor文の記述方法を学びましたが、それとは別のコードの書き方に「リスト内包表記」があります。このChapterでは、リスト内包表記の構文を学ぶことで、今までとは違う新たなコードの記述方法を覚えていきます。

リストの内包表記とは

リストの内包表記は、定義済みのリストから新たなリストを作成する際に使用します。リストの内包表記を用いることで、for文やif文が一行で記述することが可能となり、コードを簡単にすることができます。

リスト内包表記の記述方法

リスト内包表記の構文は、「処理 for 変数名 in イテラブルオブジェクト」です。実際に、リスト内包表記を使用した場合と、使用しない場合を比較しながら解説していきます。

イテラブルオブジェクト

イテラブルオブジェクトとは、リストのように複数の要素が入ったオブジェクトです。繰り返し取り出し処理が可能であることが特徴です。

まず、リスト内包表記を使用しないfor文を記述します。リストlstの要素を一つずつ取り出し2を加算して、新しいリストlst2へ追加する処理です。

test.py
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
lst2 = []
add_value = 2

for x in lst:

    lst2.append(x + add_value)

print(lst2)

出力結果

[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

次に、リスト内包表記を使用して同じ処理を記述します。

test2.py
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
lst2 = []
add_value = 2

lst2 = [x + add_value for x in lst]
print(lst2)

出力結果

[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

リスト内包表記を使用することで、for文を一行に纏めることができました。「処理 for 変数名 in イテラブルオブジェクト」の構文と照らし合わせてみましょう。「処理(x+2)for 変数名(x) in イテラブルオブジェクト(lst)」といった記述になっています。

if文を使用したリスト内包表記の記述方法

リスト内包表記では、for文と合わせてif文の使用も可能です。
リスト内の要素を取り出すfor文に加えて、除算の結果、余りが0の場合は2倍にして値をリストlst2に追加し、余りが出た場合はそのままの値をリストlst2に追加するif文の処理を記述します。
まずは、リスト内包表記を用いないで記述してみましょう。

test.py
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
lst2 = []
mul_value = 2

for x in lst:
    if x % 2 == 0:
        lst2.append(x * mul_value)
    else:
        lst2.append(x)

print(lst2)

出力結果

[1, 4, 3, 8, 5, 12, 7, 16, 9, 20]

リスト内包表記を使用して記述します。

test2.py
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
lst2 = []
mul_value = 2

lst2 = [x * mul_value if x % 2 == 0 else x for x in lst]

print(lst2)

出力結果

[1, 4, 3, 8, 5, 12, 7, 16, 9, 20]

このように、リスト内包表記を使用することで、コードを簡素化することが可能になります。しかし、処理が長いif文やネストしたfor文のように複雑な処理になる程、リスト内包表記では一行が長くなり分かりづらくなりますので、注意して使用することが大切です。

Lesson 4 Chapter 3
タプル型

リストのようなシーケンスデータを扱う型には、もう一つ「タプル」という型があります。一見似ているような型ですが、リストとは違った特徴があります。このChapterでは、タプルの特徴を学びリストとの違いを理解することで、プログラムする際にどちらを使用するのが最適かを判断できるようになることを目指します。

タプルとは

タプルはリストと同じく、シーケンスデータを扱うことが可能な型です。しかし、リストと大きく違うのは、タプルは変更不可であるという点です。タプルはイミュータブルで、リストはミュータブルであるといいます。イミュータブルは変更不可のオブジェクトを指し、ミュータブルはその逆で変更可能なオブジェクトを意味します。

Windowsの場合はコマンドプロンプト、macOSの場合はターミナルを起動させ、"python"と入力しPythonを起動させ準備してください。

タプルの定義

タプルを定義するには、括弧()内に値をカンマ(,)区切りで記述します。

>>> tup = (1,2,3,4,5,6,7,8,9)

これでタプルが定義されました。今回は、「tup」という配列名を使用していますが、配列名は任意の値で設定可能です。リストの定義が完了したら、配列名「tup」を入力して実行してください。

>>> tup

出力結果

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

type関数を使用して、タプルであることを確認しましょう。

>>> type(tup)

出力結果

<class 'tuple'>

カンマ(,)付きで定義した場合は括弧()無しでも、タプルとして定義されます。
以下の記述は全てタプルとして定義されます

tup1 = 1,
tup2 = (1,)
tup3 = ('Hello',)
tup4 = 'Hello',

type関数を使用して型を確認しましょう。

>>> print('tup1の型=' , type(tup1))
>>> print('tup2の型=' , type(tup2))
>>> print('tup3の型=' , type(tup3))
>>> print('tup4の型=' , type(tup4))

出力結果

tup1の型= <class 'tuple'>
tup2の型= <class 'tuple'>
tup3の型= <class 'tuple'>
tup4の型= <class 'tuple'>

カンマ(,)を付けることで、どの記述方法でも全てタプルとして定義されています。

要素の変更

リストと違い、タプルは要素の変更が不可能です。実際に追加処理を行い、エラーになることを確認しましょう。インデックスを指定して、タプルに要素を追加してみます。

>>> tup = (1,2,3,4,5,6,7,8,9)
>>> tup[0] = [100]

出力結果

TypeError: 'tuple' object does not support item assignment

インデックスNo.0を指定して、タプルの最初に100を追加しようとしましたが、「TypeError」が発生し追加できませんでした。このようにタプルは変更不可(イミュータブル)なオブジェクトです。

インデックスを使用した要素の取り出し(スライス)

変更不可であること以外の操作は、リスト同様に可能です。まずは、要素の取り出しを行なってみましょう。

>>> tup = (1,2,3,4,5,6,7,8,9)
>>> tup[0]

出力結果

1

インデックスの"0"を指定すると、タプルの要素"1"が取り出されました。インデックスは、"0"から始まる事に注意してください。それでは、タプルの要素"3"を取り出してみましょう。

>>> tup[2]

出力結果

3

続いて、色々な方法で要素を取り出してみましょう。複数の要素を取り出すには、インデックスをコロン(:)で区切り指定します。

要素の"1"から"2"までを取り出します。

>>> tup[0:2]
>>> tup[:2]
>>> tup[-9:-7]

出力結果

(1, 2)

要素の"3"から"5"までを取り出します。

>>> tup[2:5]
>>> tup[-7:-4]

出力結果

(3, 4, 5)

要素の"2"から最後までを取り出します。

>>> tup[1:]
>>> tup[-8:]

出力結果

(2, 3, 4, 5, 6, 7, 8, 9)

全ての要素を取り出します。

>>> tup[:]

出力結果

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

最後から順に要素を取り出します。

>>> tup[::-1]

出力結果

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

指定した数だけスキップして要素を取り出します。

>>> tup[::2]

出力結果

(1, 3, 5, 7, 9)

ネストされたタプルの作成

タプル内にさらにタプルを作成します。2つのタプルを定義して、新たなタプルにまとめてみましょう。

>>> tup1 = (1,2,3)
>>> tup2 = ('a','b','c')

2つのタプルが定義出来たら、2つをまとめるタプルを新たに定義します。

>>> tup3 = (tup1,tup2)

3つ目のタプルが定義できたら、「tup3」の要素を確認してみてください。ネストされたタプルが作成されていることが確認できるはずです。

>>> tup3

出力結果

((1, 2, 3), ('a', 'b', 'c'))

リストをネストすることも可能です。ネストされたリストの要素は、変更可能になります。2つのリストを定義して、タプルにまとめます。

>>> lst1 = [1,2,3]
>>> lst2 = ['a','b','c']
>>> tup3 = (lst1,lst2)

2つのリストをまとめたタプルを確認してみましょう。

>>> tup3

出力結果

([1, 2, 3], ['a', 'b', 'c'])

タプル内にリストが定義されています。リストの要素に変更を加え、再度タプルの確認を行います。

>>> tup3[0][2] = 100
>>> tup3

出力結果

([1, 2, 100], ['a', 'b', 'c'])

リストは変更可能(ミュータブル)なオブジェクトであるため、要素の追加が許可されました。次に、タプルへ追加してみます。

>>> tup3[0] = 100

出力結果

TypeError: 'tuple' object does not support item assignment

タプルは変更不可能(イミュータブル)なオブジェクトであるため、要素の追加はエラーとなり「TypeError」が出力されました。

Lesson 4 Chapter 4
集合型

集合型は、リスト同様に変更可能(ミュータブル)な型になりますが、重複した値を持てないことや、要素の集合に対して和や差といった集合演算を扱えるなどの特徴があります。リストとの違いや、集合演算を扱った操作まできちんと解説していきますので、集合型を用いた際のメリットを掴んでください。

集合型とは

集合型とは、リストやタプルと違い、「重複した要素を持てない」・「要素に順序がない」といったことが特徴の型になります。

Windowsの場合はコマンドプロンプト、macOSの場合はターミナルを起動させ、"python"と入力しPythonを起動させ準備してください。

集合型の定義

集合型を定義するには、波括弧{}内に値をカンマ(,)区切りで記述します。

>>> s = {1,1,2,3,4,5,5,6,7,8,9}

これで集合型が定義されました。今回は、「s」という配列名を使用していますが、配列名は任意の値で設定可能です。リストと何ら変わらないように思うかもしれませんが、定義した集合型を出力してみましょう。

>>> s

出力結果

{1, 2, 3, 4, 5, 6, 7, 8, 9}

重複して定義した1と5が、一意な値として扱われています。このように集合型は、重複した要素が取り除かれます。

type関数を使用して、集合型であることを確認しましょう。

>>> type(s)

出力結果

<class 'set'>

setは集合型を意味します。出力結果から集合型で定義されていることが確認できます。
次に、もう一つの特徴である要素に順序がないといった点について確認します。要素に順序がないということは、インデックスを持たないということです。インデックスを指定して、集合型から要素を取り出してみましょう。

>>> s[0]

出力結果

TypeError: 'set' object is not subscriptable

インデックスNo.0を指定して、要素の取り出しを行いましたが「TypeError」と出力されエラーになりました。このことから、集合型の要素には順序がないということが分かると思います。

和集合を使用した集合型の操作

「|」を使用して、2つの集合を合わせた新しい集合を作成する操作が可能です。
まず、2つの集合を定義します。

>>> s1 = {1,2,3,4,5}
>>> s2 = {6,7,8,9,10}

「|」を使用して、2つの和集合を計算します。計算結果を新しい配列「s3」として定義した後、「s3」の要素を確認してみてください。

>>> s3 = s1 | s2
>>> s3

出力結果

{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

配列「S1」と「s2」の2つを合わせた配列が、集合型で定義されました。

積集合を使用した集合型の操作

「&」を使用して、2つの集合から共通の要素を抜き出し、新しい集合を作成する操作が可能です。

>>> s1 = {1,2,3,4,5,6,7,8,9,10}
>>> s2 = {2,4,8}

「&」を使用して、2つの積集合を計算します。計算結果を新しい配列「s3」として定義した後、「s3」の要素を確認してみてください。

>>> s3 = s1 & s2
>>> s3

出力結果

{8, 2, 4}

配列「S1」と「s2」の2つで共通した要素のみの、新しい配列が集合型で定義されました。

差集合を使用した集合型の操作

「-」を使用し、一方の集合からもう一方の集合と共通する要素を削除して、新しい集合を作成する操作が可能です。

>>> s1 = {1,2,3,4,5,6,7,8,9,10}
>>> s2 = {2,4,8}

「-」を使用して、2つの差集合を計算します。計算結果を新しい配列「s3」として定義した後、「s3」の要素を確認してみてください。

>>> s3 = s1 - s2
>>> s3

出力結果

{1, 3, 5, 6, 7, 9, 10}

配列「S1」から「s2」と共通の要素である2,4,8が削除された、新しい配列が集合型で定義されました。

排他的論理和集合を使用した集合型の操作

「^」を使用して、2つの集合で共通の要素以外を合わせて、新しい集合を作成する操作が可能です。

>>> s1 = {1,2,3,4,5}
>>> s2 = {2,4,6,8,10}

「^」を使用して、2つの排他的論理和を計算します。計算結果を新しい配列「s3」として定義した後、「s3」の要素を確認してみてください。

>>> s3 = s1 ^ s2
>>> s3

出力結果

{1, 3, 5, 6, 8, 10}

配列「S1」か「s2」のどちらかには存在するが、2つの集合で重複はしていない要素が抜き出され、新しい配列が集合型で定義されました。

集合の追加メソッド

メソッド「add」を使用して、集合に要素を追加します。

>>> s = {1,2,3,4,5}
>>> s.add(100)

配列名を指定して要素が追加されているかを確認します。

>>> s

出力結果

{1, 2, 3, 4, 5, 100}

指定した値:100が追加されています。もう一度、同じ値を追加してみます。

>>> s.add(100)

再度、配列名を指定して要素を確認します。

>>> s

出力結果

{1, 2, 3, 4, 5, 100}

値:100を2回追加しましたが、重複した要素を持たない集合型であるため、要素としては1つのみしか追加されていません。追加処理はエラーになりませんが、実際に集合型に追加されるわけではないので注意してください。

集合の削除メソッド

要素を指定した部分削除

メソッド「remove」を使用して、集合の要素を削除します。集合はインデックスを持たないため、要素を直接指定して削除を行います。

>>> s = {1,2,3,4,5}
>>> s.remove(5)

配列名を指定して要素が削除されているかを確認します。

>>> s

出力結果

{1, 2, 3, 4}

指定した要素:5が削除されています。

全要素の削除

メソッド「clear」を使用して、集合の全ての要素を削除する操作が可能です。

>>> s = {1,2,3,4,5}
>>> s.clear()

配列名を指定して要素が削除されているかを確認します。

>>> s

出力結果

set()

全ての要素が削除されたことが確認できます。

Lesson 4 Chapter 5
辞書型

今まではシーケンス型として、リストやタプルについて学んできました。このChapterでは、マッピング型に分類される「辞書型」という型の扱いについて解説していきます。

辞書型とは

辞書型は、要素が"Key(キー)"と"Value(バリュー)"のセットで構成されたオブジェクトです。リストやタプルではインデックスを用いて要素の取り出し等の操作を行いましたが、辞書型は任意の"Key(キー)"を指定することで要素にアクセスすることが可能です。

Windowsの場合はコマンドプロンプト、macOSの場合はターミナルを起動させ、"python"と入力しPythonを起動させ準備してください。

辞書型の定義

辞書型を定義するには、波括弧{}を使用して定義します。集合型と同一のように思われるかもしれませんが、辞書型は波括弧{}内の値の指定方法が違っています。
辞書型は、{キー1:値1, キー2:値2, ...}のように型を定義します。

>>> d = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}

これで辞書型が定義されました。今回は、「d」という配列名を使用していますが、配列名は任意の値で設定可能です。集合型とは違い、値に対してキーもセットで定義をします。
次に、要素を取り出します。アクセスしたい要素のキーを指定します。

>>> d['name']

出力結果

'山田'

リストやタプルではインデックスを利用しましたが、辞書型は任意で設定したキーを用いて要素へアクセスします。

type関数を使用して、辞書型であることを確認しましょう。

>>> type(d)

出力結果

<class 'dict'>

dictは辞書型を意味します。出力結果から辞書型で定義されていることが確認できます。
辞書型にはもう一つ型の定義方法があります。dict(キー1=値1, キー2=値2, ...)という構文で型の生成が可能です。

>>> d = dict(name='鈴木', TEL='090-9876-5432',mail='test_python@gmail.com')

配列名を指定して要素を確認します。

>>> d

出力結果

'{'name': '鈴木', 'TEL': '090-9876-5432', 'mail': 'test_python@gmail.com'}

dictを用いて辞書型を定義する場合は、「'name'='鈴木'」ではなく、「name='鈴木'」のようにキーをクォーテーションで囲む必要はありません。

要素の変更方法

要素の変更もキーを指定することで可能です。

>>> d = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}
>>> d['name'] = '鈴木大和'

変更したキーを指定して要素を出力します。

>>> d['name']

出力結果

'鈴木大和'

キー"name"に紐付く要素「山田」が、「鈴木大和」に変更されました。

要素の追加方法

要素の追加は、キーと合わせて追加したい値を指定します。

>>> d = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}
>>> d['address'] = '東京都渋谷区'

追加したキーを指定して要素を出力します。

>>> d['address'] 

出力結果

'東京都渋谷区'

追加したキー"address"に紐付く要素「東京都渋谷区」が出力され、追加されたことが確認できます。

キーのみ取得するメソッド

辞書型のキーのみを取得したい場合は、メソッド「keys」を使用します。

>>> d = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}
>>> d.keys()

出力結果

dict_keys(['name', 'TEL', 'mail'])

バリューのみ取得するメソッド

辞書型のバリューのみを取得したい場合は、メソッド「values」を使用します。

>>> d = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}
>>> d.values()

出力結果

dict_values(['山田', '090-1234-5678', 'pythonlesson@gmail.com'])

他の辞書型を使用して上書きするメソッド

一方の辞書型で、もう一方を上書きするには、メソッド「update」を使用します。
まず、2つの辞書型を定義します。

>>> d1 = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}
>>> d2 = {'name': '鈴木', 'address': '東京都渋谷区'}

「d1」を「d2」で上書きします。

>>> d1.update(d2)

配列「d1」の要素を出力します。

>>> d1

出力結果

{'name': '鈴木', 'TEL': '090-1234-5678', 'mail': 'pythonlesson@gmail.com', 'address': '東京都渋谷区'}

d1のキー"name"に紐付く要素「山田」が、d2のキー"name"に紐付く「鈴木」に上書され、d2のみに存在するキー"address"に紐付く「東京都渋谷区」が追加されました。

辞書型の削除メソッド

メソッド「del」を使用して、要素の削除が可能です。

>>> d = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}
>>> del d['TEL']

配列「d」の要素を出力します。

>>> d

出力結果

{'name': '山田', 'mail': 'pythonlesson@gmail.com'}

キー"TEL"と紐付く要素「090-1234-5678」が削除されました。

次は、リストでも使用したメソッド「pop」を使用します。

>>> d = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}
>>> d.pop('name')

コマンドの実行と同時に山田が表示されるはずです。delは削除でしたが、popは取り出しを意味します。このため取り出した要素を表示したわけです。

出力結果

'山田'

配列「d」の要素を確認してください。delと同じく指定した要素が削除されているはずです。

>>> d

出力結果

{'TEL': '090-1234-5678', 'mail': 'pythonlesson@gmail.com'}

最後に、メソッド「clear」を使用した削除方法を解説します。

>>> d = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}
>>> d.clear()

配列「d」の要素を確認してください。空の型が残っているのが確認できるはずです。

>>> d

出力結果

{}

メソッド「clear」は、あくまで型の中身だけを削除します。型は残っているため、再度値を設定することが可能です。

>>> d = {'x': 10, 'y': 20}

配列「d」の要素を確認してください。

>>> d

出力結果

{'x': 10, 'y': 20}

配列名は「d」のままですが、要素が変更されています。

辞書型のコピー

辞書型もリスト同様に、「参照渡し」と「値渡し」の2通りのコピーがあるので注意が必要です。

参照渡しのコピー

参照渡しのコピー方法です。

>>> cp1 = {'x': 10, 'y': 20}
>>> cp2 = cp1
>>> cp2

出力結果

{'x': 10, 'y': 20}

「cp2」に、「cp1」がコピーされました。「cp2」の要素に変更を加えます。

>>> cp2['x'] = 30

「cp1」・「cp2」、それぞれの要素を出力してみます。

>>> cp1
>>> cp2

出力結果

{'x': 30, 'y': 20}
{'x': 30, 'y': 20}

「cp2」への変更が、「cp1」にも適用されてしまいました。参照渡しのコピーでは、このようにコピー元の要素にも変更が適用されます。

値渡しのコピー

参照渡しのコピーでは、想定外に要素を変更してしまう可能性があります。指定した配列の要素のみを変更するには、メソッド「copy」を使用した値渡しのコピーを行います。

>>> cp1 = {'x': 10, 'y': 20}
>>> cp2 = cp1.copy()
>>> cp2

出力結果

{'x': 10, 'y': 20}

メソッド「copy」を使用して、「cp1」を「cp2」にコピーしました。「cp2」の要素に変更を加えます。

cp2['x'] = 30

「cp1」・「cp2」、それぞれの要素を出力してみます。

>>> cp1
>>> cp2

出力結果

{'x': 10, 'y': 20}
{'x': 30, 'y': 20}

参照渡しのコピーとは違い、メソッド「copy」を使用した値渡しのコピーでは、「cp2」のみ変更が適用されています。

Lesson 4 Chapter 6
ループ

ループ処理は、Lesson4のChapter7で解説したとおり、「ある条件に満たすまで同じ処理を繰り返す」・「指定した回数処理を繰り返す」といった、コンピュータが最も得意とする繰り返し処理を実行させるためのプログラムテクニックです。このチャプターでは、Pythonの標準ライブラリのメソッドや関数とループ処理を組み合わせた活用方法を解説します。

itemsメソッド

辞書型を学習した際に、キーとバリューを用いて型を定義しましたが、メソッド「items」は、辞書型からキーとバリューを取得するメソッドです。itemsを利用したループ処理を記述していきましょう。

まずは、itemsの動作を確認します。以下のコードを記述して実行してください。

items_test.py
d = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}

print(d.items())

出力結果

dict_items([('name', '山田'), ('TEL', '090-1234-5678'), ('mail', 'pythonlesson@gmail.com')])

print関数の出力結果から、キーとバリューのどちらも取得できていることが確認できます。

次に、for文のループ処理内でitemsを利用します。

items_test.py
d = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}

for k,v in d.items():
    print(k,'=',v)

出力結果

name = 山田
TEL = 090-1234-5678
mail = pythonlesson@gmail.com

for文で指定した変数kにはキーが、変数vにはバリューが設定されprint関数によって出力されました。
キーとバリューをそれぞれprint関数で分けて出力してみます。

items_test.py
d = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}

for k,v in d.items():
    print('===================================')
    print('キー = ', k)
    print('バリュー = ', v)

出力結果

===================================
キー =  name
バリュー =  山田
===================================
キー =  TEL
バリュー =  090-1234-5678
===================================
キー =  mail
バリュー =  pythonlesson@gmail.com

このように、メソッド「items」はキーとバリューを合わせて取得し、for文の変数に格納可能なため、それぞれの値を格納した変数を用いた処理が可能になります。

enumerate関数

今までリストやタプルの操作時にインデックスを使用してきましたが、「enumerate」関数はfor文内で、インデックス番号を付与することが可能になります。インデックス番号は、自動付与だけでなく、任意の番号を付与することも可能です。
まずは、enumerate関数を使用せずにfor文を記述します。

enumerate_test.py
lst = ['morning', 'afternoon', 'evening', 'night']

for x in lst:
    print(x)

出力結果

morning
afternoon
evening
night

enumerate関数を使用して、インデックスを付与します。

enumerate_test.py
lst = ['morning','afternoon','evening','night']

for i, x in enumerate(lst):
    print(i, x)

出力結果

0 morning
1 afternoon
2 evening
3 night

0〜3までのインデックスが付与されました。
インデックスは0からではなく、任意の開始番号とすることも可能です。enumerate関数の第二引数に開始番号を指定します。

enumerate_test.py
lst = ['morning', 'afternoon', 'evening', 'night']

for i, x in enumerate(lst,10):
    print(i, x)

出力結果

10 morning
11 afternoon
12 evening
13 night

文字列へインデックスを付与することも可能です。

enumerate_test.py
str = 'GoodMorning'

for i, x in enumerate(str):
    print(i, x)

出力結果

0 G
1 o
2 o
3 d
4 M
5 o
6 r
7 n
8 i
9 n
10 g

zip関数

リストの要素を取り出して、for文内でその要素を利用する際に、利用したいリスト自体が2つ、3つと複数になった場合に便利なのが「zip」関数です。
まずは、zip関数を使用しないで、3つのリストから要素を取り出して出力するfor文を記述していきましょう。itemsメソッドで使用した名前・住所・メールの情報が複数人分存在した場合に、それぞれの情報の出力が必要になったことを想定してコーディングを行います。
3人分の情報を、名前・住所・メールに分けてリストを作成します。

zip_test.py
name = ['山田', '田中', '鈴木']
tel = ['090-1234-5678', '080-5678-1234', '090-9876-5432']
mail = ['yamada_test@gmail.com', 'tanaka_test@gmail.com', 'suzuki_test@gmail.com']

3人のそれぞれの情報を、for文を使用して一人ずつの情報に纏めて出力してみます。

zip_test.py
name = ['山田', '田中', '鈴木']
tel = ['090-1234-5678', '080-5678-1234', '090-9876-5432']
mail = ['yamada_test@gmail.com', 'tanaka_test@gmail.com', 'suzuki_test@gmail.com']

for i in range(len(name)):
    print(name[i], tel[i], mail[i])

出力結果

山田 090-1234-5678 yamada_test@gmail.com
田中 080-5678-1234 tanaka_test@gmail.com
鈴木 090-9876-5432 suzuki_test@gmail.com

名前・住所・メールを一人ずつの情報に纏めて出力できました。
print関数で出力する際に、リストの要素をインデックス指定(name[i])で出力していますが、どこからどこまでのインデックスを指定するのかを判別する必要があります。そこで、for文の最初にlen関数を使って(len(name))、リストnameの要素数を取得しています。取得した要素数をさらにrange関数を使用(range(len(name)))することで、変数iには0〜2までが繰り返し設定されます。結果的に、print関数の要素を取り出すためのインデックスにも0〜2が繰り返し設定され、一人ずつの情報を纏めて出力することを可能にしました。

次は、zip関数を使用して同じ処理を書き換えましょう。

zip_test.py
name = ['山田', '田中', '鈴木']
tel = ['090-1234-5678', '080-5678-1234', '090-9876-5432']
mail = ['yamada_test@gmail.com', 'tanaka_test@gmail.com', 'suzuki_test@gmail.com']

for name, tel, mail in zip(name, tel, mail):
    print(name, tel, mail)

出力結果

山田 090-1234-5678 yamada_test@gmail.com
田中 080-5678-1234 tanaka_test@gmail.com
鈴木 090-9876-5432 suzuki_test@gmail.com

zip関数は、このように要素を纏めて取得することが可能です。最初のコードのように、あえてインデックスを取得することもなければ、出力する際のインデックス指定も不要になり、コードがシンプルになりました。

リストの要素数が異なる場合

リストの要素数が異なる場合は、どのような挙動になるのでしょうか。電話番号を一つ削除して要素数を変えて実行してみます。

zip_test.py
name = ['山田', '田中', '鈴木']
tel = ['090-1234-5678', '090-9876-5432']
mail = ['yamada_test@gmail.com', 'tanaka_test@gmail.com', 'suzuki_test@gmail.com']

for name, tel, mail in zip(name, tel, mail):
    print(name, tel, mail)

出力結果

山田 090-1234-5678 yamada_test@gmail.com
田中 090-9876-5432 tanaka_test@gmail.com

正常に繰り返し処理が行われましたが、出力は2人分となりました。要素数が違っていても、処理は実行されますが、その場合は少ない要素数に合わせてループ処理が実行されることを覚えておきましょう。

リストの要素が異なる場合はエラーとする

リストの要素が異なる場合でもエラーにならないことは解説しましたが、逆に、エラーとしたい場合もあります。その時は、引数に「strict」を用いることで、あえてエラーにすることができます。

zip_test.py
name = ['山田', '田中', '鈴木']
tel = ['090-1234-5678', '090-9876-5432']
mail = ['yamada_test@gmail.com', 'tanaka_test@gmail.com', 'suzuki_test@gmail.com']

for name, tel, mail in zip(name, tel, mail, strict=True):
    print(name, tel, mail)

出力結果

TypeError: zip() takes no keyword arguments

「TypeError」が出力されて、エラーとなりました。

引数「strict」について

引数「strict」は、Python3.10以降で使用可能な引数です。それより前のバージョンでは、使用不可となりますでの気をつけてください。

sorted/reversed関数

for文は「for 変数 in イテラブルオブジェクト:」と指定した後に、処理内容を記述しました。処理の順番はイテラブルオブジェクトで指定した要素を一つずつ順番に取り出し、処理内容に記述した処理が実行されますが、その動作については、今までのサンプルコードの実行により確認できていると思います。
しかし、処理によっては、イテラブルオブジェクトを昇順や降順に並び替えてから処理を実行させたい場合もあります。そこで利用するのが、「sorted/reversed」関数です。

sorted関数

指定されたイテラブルオブジェクトが順序性を保っていない場合、「sorted関数」を使用して昇順に並び替えてからfor文を実行することが可能です。
リストの要素を昇順に並び替えてから、for文を実行するコードを記述しましょう。

sorted1_test.py
lst = [2, 10, 5, 77, 8, 1, 30]

for x in sorted(lst):
    print(x)

出力結果

1
2
5
8
10
30
77

本来、イテラブルオブジェクトにはリストlstが与えられるので処理順序は、リストlstの左の要素:2から順番に処理され、最後は要素:30になりますが、sorted関数で昇順に並び替えた結果を取り出しているので、print関数で出力される順番がリストlstの並び順ではなくなっています。
このように、イテラブルオブジェクトに指定される値は順序性を保ってはいないが、処理は順序性を保ち実行したい際には、sorted関数を使用します。
降順に並び替えるには、以下のコードのように、引数に「reverse=True」を指定します。

lst = [2, 10, 5, 77, 8, 1, 30]

for x in sorted(lst, reverse=True):
    print(x)

出力結果

77
30
10
8
5
2
1

次は、文字列を並び変えてみましょう。

sorted2_test.py
lst = ['morning','afternoon','evening','night']

for x in sorted(lst):
    print(x)

出力結果

afternoon
evening
morning
night

アルファベット順に並び替えられた後に、for文の処理が実行されていることが出力結果から確認できます。

sorted関数と同じ並び替えの関数として、Chapter1でsort関数を学びました。sorted関数とsort関数の違いは何になるのでしょうか。2つの違いを確認しましょう。
最初に、sorted関数の動作を確認します。
Windowsの場合はコマンドプロンプト、macOSの場合はターミナルを起動させ、"python"と入力しPythonを起動させ準備してください。

>>> lst1 = [2,10,5,77,8,1,30]
>>> sorted_lst = sorted(lst1)
>>> print('sorted関数 =', sorted_lst)

出力結果

sorted関数 = [1, 2, 5, 8, 10, 30, 77]

昇順に並び替えられた結果が出力されました。元のリストlst1の要素を確認しましょう。

>>> lst1

出力結果

[2, 10, 5, 77, 8, 1, 30]

元のリストlst1には変更が加わっていません。

次に、sort関数を使用します。

>>> lst2 = [5, 30, 8, 66, 2, 5, 1]
>>> sort_lst = lst2.sort()
>>> print('sort関数 =', sort_lst)

出力結果

sort関数 = None

「None」が出力され、新しいリストsort_lst2は定義されていません。リストlst2の要素を確認します

>>> lst2

出力結果

[1, 2, 5, 5, 8, 30, 66]

出力結果から分かるとおり、リストlst2が昇順に並び変えられました。

このように、sorted関数は元のリストは変更されませんが、sort関数は元のリストに変更を加えるといった違いがあります。

reversed関数

「reversed関数」は、イテラブルオブジェクトを逆順にします。降順ではなく、逆順であることに注意してください。reversed関数を使用した、for文のコードを記述します。

reversed_test.py
lst = [2, 10, 5, 77, 8, 1, 30]

for x in reversed(lst):
    print(x)

出力結果

30
1
8
77
5
10
2

リストlstの要素が、逆順に並び替えられた結果が出力されました。[77, 30, 10, 8, 5, 2, 1]の降順ではないことに注意して下さい。
sorted関数同様に、reversed関数と同じ逆順の並び替え関数として、Chapter1でreverse関数を学びました。こちらもsort関数とsorted関数の違い同様、元のリストを書き換えるかそうでないかの違いとなります。