見出し画像

CourseraでPython Data Structuresを受講した(前編)

ミシガン大学がCoursera上で開講しているオンライン講座"Python for Everybody"の第1コース、”Programming for Everybody"の受講を終えて一息ついたのもつかの間、Dr. Chuckから「この講義は前半みたいなもんなんで、まだまだこれからです。一休みしたら後半の講義に戻ってきてくださいね!!」と言われてしまったので第2コースを受講します。(強制!?)

第1コースの講義録はこちらからどうぞ↓

第2コースは"Python Data Structures"という名前になっており、文字通りさまざまなデータを扱うためのPythonの基本動作を学んでいきます。


1.Week 1

<テキストの範囲>
Chapter 6: Strings

Dr. Chuckによると、このWeek 1の講義までがいわば「素材」であり、Week 2の復習を経てWeek 3の講義からいよいよ「料理」に入っていきます。最後の素材は文字列操作。Pythonでは文字列の操作が他の言語と違っているところが多いので、表現方法も含めて理解しておきましょう。

city_name = 'Tokyo'
oneletter = city_name[1] #...T(0) o(1) k(2) y(3) o(4)
print(oneletter)

x = 4
g = city_name[x - 2]
print(g)

このプログラムでは、最初の3行で文字列Tokyoの2文字目を変数oneletterに代入します。次に、変数gに代入される文字は、city_name[2]ですから3文字目のkになります。出力結果は以下のようになります。

o
k

文字列の個数を確認するには、len関数を用います。

city_name = 'Tokyo'
x = len(city_name)
print(x)

このプログラムの例では、Tokyoの文字数5がxに代入されます。

次に、1文字ずつ出力される方法を見てみましょう。カウンタを用いると、whileループを用いて以下のように表現できます。

city_name = 'Tokyo'
index = 0
while index < len(city_name): #...[1]
    letter = city_name[index]
    print(index, letter)
    index = index + 1
print('Done!!')

ここで、[1]は5回繰り返すのであるから<=ではないのか?という疑問がわいてきます。変数indexは0からスタートしているので、0, 1, 2, 3, 4までが正しいループ回数になります。なお、<=と記述すると正しく文字列が取得できなくなるため、エラーとなります。

出力結果は、以下のようになります。

0 T
1 o
2 k
3 y
4 o
Done!!

このようなプログラムの方法は他の言語も同じですが、Pythonではforループを使った構文で操作することができます。

city_name = 'Tokyo'
for letter in city_name: #...[1]
    print(letter)
print('Done!!')

ここで、[1]はletterという変数をT→o→k→y→oというように進めます。そのため、letterそのものを出力してしまえば1文字ずつ出力することができるのです。出力結果は以下のように、カウンタの数はありません。

T
o
k
y
o
Done!!

変数letterのように、for文でループさせるカウンタのような役割をする変数をiteration variableといいます。Iteration variableはinの後にある一組の文字列を順番に見ていきます。

文字列を切り出すときは、[a:b]のようにカッコ[]とコロンで指定します。

str = 'Time is money.'
print(str[3:5]) #...[1]
print(str[2:]) #...[2]
print(str[:3]) #...[3]
print(str[:]) #...[4]

[1]は、文字列の切り出す始点(最初の文字はゼロであることに注意!)と終点が指定されています。[2]や[3]のように、片方だけの指定であれば、始点または終点まで全部のテキストが切り出されます。[4]のように何も指定しなければ、文字列すべてを切り出します。したがって、出力結果は、

e i
me is money.
Time
Time is money.

となります。

Pythonによる文字列の操作では、+演算子を使うこともあります。その場合、勝手にスペースが入るわけではないので、気をつけましょう。

a = 'Tokyo'
b = 'Osaka'
c = a + b
print(c)

この出力結果は、もちろん

TokyoOsaka

になってしまいます。

文字列の検索において、inを使うことができます。inは含まれているかどうかを判定し、TrueまたはFalseを返します。

city_name = 'Tokyo'
if 'o' in city_name:
   print('o is in Tokyo!!')

このように条件式でも使うことができます。

Dr. Chuckは講義の途中、「文字列はオブジェクトとして認識する」「stringライブラリを使う」と発言しますが、今のところは特にオブジェクトとは何か?を考える必要はありません。文字列を操作するコマンドの表記方法が若干今までの表記法と異なるようだ、という程度の理解で良いでしょう。

greetings = 'Hello Bob'
a = greetings.lower()
print(a)
print('Hi There'.lower())

このプログラムを実行すると、

hello bob
hi there

と表示されます。文字列の変数greetingsの後に.lower()という関数を指定すると、文字列がすべて小文字に変換されます。これは最後の行のように、print関数の中でも機能します。

次に、find関数を見てみましょう。

city_name = 'Tokyo'
pos = city_name.find('ok') #...[1]
print(pos)
pos = city_name.find('z') #...[2]
print(pos)

[1]では、city_name変数の中からokがどの位置にあるかを判定し、検索対象が見つかればその最初の位置を返します。この場合は、2文字目ですから1を返します。
一方、[2]ではcity_name変数にあるTokyoという文字の中に検索対象のzはありませんから、pos変数には-1が返されます。

文字列の一部を変更するには、replace関数を使います。

city_name = 'Kanazawa'
a = city_name.replace('za', 'ga') #...[1]
print(a)
b = city_name.replace('a', 'g') #...[2]
print(b)

replace関数は[1]のように、ドットの前で指定する文字列に対し、カッコの1つ目にある文字列を2つ目の文字列に変更します。該当する文字列すべてを変換してしまうため、[2]のように複数の文字列が該当する場合、すべて変換されてしまいます。したがって、出力結果は以下のようになります。

Kanagawa
Kgngzgwg

目に見えない空白を消すには、左側を消すにはlstrip関数、右側を消すにはrstrip関数、両側を消すにはstrip関数を使います。

さて、次は少し応用をしてみます。

data = 'From koreha_sample_desuyo@kyoko-u.ac.jp Sat Jun 6 02:03:34 2015' #...[1]
atpos = data.find('@') #...[2]
print(atpos)
sppos = data.find(' ', atpos) #...[3]
print(sppos)
host = data[atpos+1 : sppos] #...[4]
print(host)

[1]のdataは、メールのヘッダーの1行目と考えてみてください。このプログラムは、メールのヘッダーからPythonプログラムを用いてkyoko-u.ac.jpというホスト名を抜き出す操作をします。

[2]で、まず@が何番目の文字列にあるかを判断します。26文字目ですね。注意しなけばならないのは、findが返す値は0からスタートしているので、26文字目ということはatpos変数は25になっています。次に、atpos変数(つまり25)をスタート地点として、次の空白文字が何文字目にあるかを[3]で検索しています。(最初からカウントして)40文字目ですね。したがって、spposは39という数が入っています。抜き出す文字列は、27文字目から40文字目ですから、data[26:39]と指定すれば正しいホスト名が取得できることになります。

25
39
kyoko-u.ac.jp

上の文章が読みにくい場合は〇文字目、という部分は無視して0からカウントするように覚えておくと、指定する文字列の場所がよりクリアに理解できると思います。


2.Week 2

この講義は、第1コースでカバーしたPythonのインストール方法、オンラインツールの使い方、スクリーンショットの取り方などの復習チャプターになりますので、ここでの解説は割愛します。ちなみに私はエディタにatom、プログラミングにはAnacondaを使用しています。詳しくは、Pythonに関する一番はじめの記事をご参照ください。


3.Week 3

<テキストの範囲>
Chapter 7: Files

今まではCPUとメインメモリの間の処理がメインでしたが、今回からはセカンダリメモリ(補助記憶装置:HDDやUSDメモリなど)を使ったファイル操作を学んでいきます。しばらくの間は、テキストファイルを読み込んで処理をしていくプログラムを作っていきます。実際にデータベースなどを操作するようになるのは第4コースからになります。

ファイルを開くには、open()という関数を使います。具体的には、

g = open('mbox.txt', 'r')

というようなプログラムになりますが、この構文では、変数gに何かを代入する形式になっていますね。ここで、変数gはfile handleというファイルを操作する値が入っています。open関数の中の一つ目にファイル名、二つ目にファイルの開き方を指定します。読み取り専用であれば'r'、書き込みを行う時は'w'と書きます。
File handleによって、openやread、write、closeといったような命令を実行させることができるようになります。

テキストの中に改行を含める場合は、\nをテキストの中に埋め込みます。

a = 'Hello\nWorld!!'
print(a)

このプログラムの実行結果は、

Hello
World!!

となります。

次に、file handleを用いたテキストデータの読み込みを学習します。具体的には、forループを用いて、

xfile = open('mbox.txt') #...[1]
for point_a in xfile: #...[2]
    print(point_a)

このプログラムでは、[1]でファイルを開きます。[2]で、ファイルを1行ずつ読んでいき、ファイルの最後になるまでfor文で繰り返します。したがって、このプログラムでは、mbox.txtの一行ずつ表示することで全文を表示することができます。

応用編として、ファイルの行数をカウントするプログラムを書いてみましょう。

xfile = open('mbox.txt')
count = 0
for line in xflie:
    count = count + 1
print('Total number of line is:', count)

さらに応用編として、ファイルを1行ずつ読まずに、read関数で全文を一度に読み込んでしまうこともできます。

xfile = open('mbox.txt')
wholetxt = xfile.read()
print(len(wholetxt))
print(whiletxt[:20])

これによって、文字数のカウントや文字列の抜き出しなど、さまざまな操作を行うことができます。なお、変数wholetxtには改行コード\nが含まれています。

次に、特定の文字を含む列だけを抜き出すプログラムを書いてみましょう。以下のprice.txtについて、From:を含む行だけを抜き出してみます。

From: Apple
To: Fish
Price: $20
From: Banana
To: Mountain
Price: $15

プログラムとしては、

fhand = open('price.txt')
for line in fhand:
    if line.startswith('From: '): #...[1]
        print(line)

というように書けます。[1]にあるstartwith関数を用いて、カッコで囲まれる文字列から始まる行かどうかを判定しています。条件に該当すると、print関数でその行を表示していきます。

しかしながら、このプログラムでは空白行が余計に入ってきてしまいます。

From: Apple

From: Banana

これは、for文で繰り返される時に用いられる文字列lineが\nを含んでいることに加えて、print関数を実行することで自動的に改行が入ってしまうためです。これを回避するため、rstrip関数を用いて右側にある空白(\nを含む)をカットすることが必要となります。

fhand = open('price.txt')
for line in fhand:
    line = line.rstrip() #...[1]
    if line.startswith('From: '):
        print(line)

[1]の行を挿入し、lineという文字列に\nを含まない形式にするとprint関数で挿入される\nと元々テキストから読み込んできた\nが重複せずに済む、というわけです。

また、'$'を含まない行に対しては何もしない、という処理をしたい場合は、

fhand = open('price.txt')
for line in fhand:
    line = line.rstrip()
    if not '$' in line:
        continue
    print(line)

という形でcontinueにより強制的に次のループに進むように記述すると、行の中で'$'の文字が含まれなければ最後のprintは実行されずに次のループに進みます。


今回はここまでにして、次回、リストやディクショナリといった構造の操作を取り扱っていきます。
それでは、次のコースのエントリもお楽しみに!

この記事が気に入ったらサポートをしてみませんか?