早いものでもう第6週目に突入。待ちに待ったPythonの講義。講義の内容は、CとPythonの基本的な構文を比較しながら、C言語で一度書いたプログラムをPythonに書き換えながら進んでいく。そして、最後に応用編ということで、Pythonでは音声認識、画像認識、QRコードの生成など、非常に簡単にできてしまうことが紹介される。今回の講義だけで、Pythonが自由自在に使えるようにはならないが、C言語との比較で教わるため、何が違うのかというのが非常に分かりやすかった。
パイソンの基本(Python basics)
まずは、Pythonの基本的な記述方法をC言語と比較しながら。
hello.c -> hello.py
printf
の代わりに print
。最後の ;
セミコロンも必要ない。
printf("hello, world");
print("hello, world")
hello_name.c -> hello_name.py
CS50 library等のライブラリーからインポートする場合は、#include <cs50.h>
ではなく、from cs50 import
と書く。また、from cs50 import get_string
のように、特定の関数を指定することも可能。また、複数の関数を同じライブラリーからインポートする場合は、from cs50 import get_string, get_int, get_float
のように一行で書くこともできる。
C(hello_name.c)
// get_string and printf with %s
#include <cs50.h>
#include <stdio.h>
int main(void)
{
string answer = get_string("What's your name? ");
printf("hello, %sn", answer);
}
Python(hello_name.py)
# get_string and print, with concatenation
from cs50 import get_string
answer = get_string("What's your name? ")
print("hello, " + answer)
C言語では、%s
のようにplaceholderが必要だったが、Pythonではそれが必要ない。上記の例以外にも、print(f"hello, {answer})
と f"..."
と指定できる。
if 分などの条件分岐は、次のようになる。C言語のように、括弧を使う必要はなく、代わりに :
コロンを最後に付け、次の行からは必ずインデントすることによって、条件分岐後のプログラムであることが分かる。また、else if
ではなく、elif
と書く。
if x < y:
print("x is less than y")
elif x > y:
print("x is greater than y")
else:
print("x is equal to y")
Boolean(ブーリアン)型も記述が異なる。True
と False
の先頭文字は大文字となる。
while True:
print("hello, world")
ループ(while
)の記述も異なる。
i = 0
while i < 3:
print("hello, world")
i += 1
ループ(for
)の記述も異なる。Pythonでは、予め指定したリストに入っている数字を実行できる。以下の構文では、初期値が i = 0
となり、次に、2つ目の要素の 1
が実行され、次に3つ目と続いていく。
for i in [0, 1, 2]:
print("cough")
Python独特の記述方法で、range
関数がある。例えば、次のように記述すると、range(3)
は、0
、1
、2
を意味する。range()
違う引数を取ることもできる。Pythonの公式の文書にはを参照したらたくさんあることがわかる。
for i in range(3):
print("cough")
例えば、range(0, 101, 2)
は、0
から 100
(101は含まないため)まで、2
刻みで増えていく。i
を出力したい場合も、print(i)
のみと非常にシンプル。このように、パイソンでは多くの記述方法があるため、最も広く使われる方法は、Pythonic(パイソニック)などと表現される。
Python(パイソン)のデータ型には次がある。
bool
(真偽値)、True
(真)orFalse
(偽)float
(小数点)int
(整数)str
(文字列)range
(レンジ、範囲) 連続した数字。正しくはデータ型ではなく、class
型。list
(リスト) 一覧になったデータ。Cの配列に似ているが、配列のサイズを動的に変えられるところがPythonの特徴tuple
(タプル)XとY軸、経度と緯度のような整理されたデータdict
(辞書)ハッシュ表に似たものset
(セット)重複していないデータ
例(Examples)
Pythonの便利なところは数多くのライブラリーが既に存在していて、C言語のようにLow levelなプログラムは意識せずに、High levelなプログラムに集中できるところである。
例えば、過去の課題である画像をぼかすというプログラムを書いたが、ピクセルごとの操作が必要で非常に複雑だった。でもそれが、Pythonだと次のようになる。Image
と ImageFilter
とい関数を PIL
ライブラリーから import
すれば、画像をぼかす機能が使えるようになる。
from PIL import Image, ImageFilter
before = Image.open("bridge.bmp")
after = before.filter(ImageFilter.BoxBlur(1))
after.save("out.bmp")
Image.open
で画像ファイルを開き、before
変数に代入。そのファイルに .
に filter
関数を使って、ボケ処理を加える。このとき、BoxBlur(1)
の (1)
は、上下左右 1
ピクセルずつ参照してぼかすということ。ボケの度合いを増やしたい場合は、この数字を増やせば良い。
さらに、dictionary(辞書)は次のように作ることができる。
words = set()
def load(dictionary):
file = open(dictionary, "r")
for line in file:
words.add(line.rstrip())
file.close()
return True
def check(word):
if word.lower() in words:
return True
else:
return False
def size():
return len(words)
def unload():
return True
まず、words
という set
型を準備する。Pythonは、main
関数は必ず必要なわけではないので、いきなり関数を宣言することができる。 def load()
で関数を宣言でき、今回は 引数に dictionary
を、return
には型を宣言する必要がないため何も記述していない。open
でファイルを開き、for line in file:
でファイルの中のすべての行を for
文の条件として実行できる。words
(set
型)というデータの一覧が入っているセット型に、add
関数でデータを追加し、最後に .rstrip
関数を使って改行を取り除く処理をする。
C言語のプログラムでは、既に辞書にデータが入っている場合は、check
関数を使って、確認する必要があった。Pythonでも同じだが、大文字小文字を揃えるために、全て小文字にするためには、 if word.lower() in words
で統一することができる。
辞書に追加されたデータの数を知るためには、len(words)
で words
に入っているデータの長さを知ることができ、結果が返される。
ただし、プログラムの実行スピードは、C言語の方がPythonで書いた上のプログラムより圧倒的に速い。何故か?C言語は、メモリのサイズを定義したり、配列処理をしたりをしていたが、Pythonにはそれをしない。Pythonは、その分Python言語をコンピュータが分かる言語に変換する必要があり、つまり翻訳が必要で、その分時間がかかることになる。
インプット、条件分岐(Input, conditions)
- CS50 library の
get_int
を使わずにユーザからinput
を求めるには、input
関数を使う
answer = input("What's your name? ")
print(f"hello, {answer}")
- 2つの整数の足し算をするためには(コメントは、
//
ではなく、#
で指定する。):
from cs50 import get_int
# Prompt user for x
x = get_int("x: ")
# Prompt user for y
y = get_int("y: ")
# Perform addition
print(x + y)
- CS50 library を使わずに、input 関数を使った場合は、文字列として認識される:
# Prompt user for x
x = input("x: ")
# Prompt user for y
y = input("y: ")
# Perform addition
print(x + y)
- よって、これを整数型に変換するためにはキャストを使う。が、もしユーザが整数を入力しなかった場合はエラー処理が必要なため、ライブラリーを使うことをオススメする。
# Prompt user for x
x = int(input("x: "))
# Prompt user for y
y = int(input("y: "))
# Perform addition
print(x + y)
- 割り算をするには:
# Prompt user for x
x = int(input("x: "))
# Prompt user for y
y = int(input("y: "))
# Perform division
print(x / y)
- 条件分岐文を表現するには:
from cs50 import get_int
x = get_int("x: ")
y = get_int("y: ")
if x < y:
print("x is less than y")
elif x > y:
print("x is greater than y")
else:
print("x is equal to y")
- 特定の関数ではなくCS50 libraryのすべてを
import
する場合は、プログラムは以下のように表現する。これは、CS50以外にもライブラリーをimport
していて、その中にget_int
が存在した場合に、コンピュータがどちらを使って良いか判断できないからである。よって、cs50.get_int()
と指定する必要がある。
import cs50
x = cs50.get_int("x: ")
y = cs50.get_int("y: ")
- 文字列を比較するには
==
で可能:
from cs50 import get_string
s = get_string("Do you agree? ")
if s == "Y" or s == "y":
print("Agreed.")
elif s == "N" or s == "n":
print("Not agreed.")
if s.lower() in ["y", "yes"]:
と宣言することも可能
from cs50 import get_string
s = get_string("Do you agree? ")
if s.lower() in ["y", "yes"]:
print("Agreed.")
elif s.lower() in ["n", "no"]:
print("Not agreed.")
ミャオ(meow)
C言語では、main
関数の宣言が必要だった、meow.cもPythonにかかれば次のようになる。
// Opportunity for better design
#include <stdio.h>
int main(void)
{
printf("meown");
printf("meown");
printf("meown");
}
# Opportunity for better design
print("meow")
print("meow")
print("meow")
また、for
文を使った場合は次のようにループ文にできる。ここでもPythonは行数が2行で実現できる。
// Better design
#include <stdio.h>
int main(void)
{
for (int i = 0; i < 3; i++)
{
printf("meown");
}
}
# Better design
for i in range(3):
print("meow")
meow
関数を作って呼び出すこともできる。
// Abstraction
#include <stdio.h>
void meow(void);
int main(void)
{
for (int i = 0; i < 3; i++)
{
meow();
}
}
// Meow once
void meow(void)
{
printf("meown");
}
ここでは、main
関数がないと NameError: name 'meow' is not defined
というエラーになってしまう。これは、プログラムは上から順番に処理されるからである。C言語では、Prototypeを使って、関数を先に宣言したが、Pythonにはそれがない。そのため、Pythonでは、一般的には main
関数を最初に宣言しプログラムの最後に main()
を宣言する必要がある。これは、Pythonの独特なところだろうか。
# Abstraction
def main():
for i in range(3):
meow()
# Meow once
def meow():
print("meow")
main()
// Abstraction with parameterization
#include <stdio.h>
void meow(int n);
int main(void)
{
meow(3);
}
// Meow some number of times
void meow(int n)
{
for (int i = 0; i < n; i++)
{
printf("meown");
}
}
# Abstraction with parameterization
def main():
meow(3)
# Meow some number of times
def meow(n):
for i in range(n):
print("meow")
main()
get_positive_int
C言語で存在した do while loop
が Python では存在しない。代わりに、無限ループ(while True:
)を作り、条件に合致した場合は、break
する。break
する場所は、while
文と同じ場所(インデント)にある return
文となる。
from cs50 import get_int
def main():
i = get_positive_int()
print(i)
def get_positive_int():
while True:
n = get_int("Positive Integer: ")
if n > 0:
break
return n
main()
マリオ(Mario)
横に並んだ?を4つ出力したい場合は、print
関数に第2引数を次のように(end=""
)指定する。また、最後の行は改行したいため、最後にprint()
を指示する。Pythonの print
関数はデフォルトで改行されるのは、第2引数に end="n"
となっているためであり、こういった処理が必要。
for i in range(4):
print("?", end="")
print()
もしくは、ループを書く必要もなく、4を掛け算してあげれば、4回出力できる。
print("?" * 4)
ループの中にループを書くことも可能。
for i in range(3):
for j in range(3):
print("#", end="")
print()
オーバーフロー(Overflow, imprecision)
Pythonでは、自動的にメモリ領域を増やしていくため、整数型はoverflowしない(float
ではする)。よって、次のプログラムは無限に実行される。
i = 1
while True:
print(i)
i *= 2
リスト、文字列(Lists, strings)
リストを作る際に予めサイズを宣言する必要はなく、score = [72, 73, 33]
のように []
でデータを囲めば勝手に処理してくれる。
scores = [72, 73, 33]
print("Average: " + str(sum(scores) / len(scores))
Python では、sum
関数(合計)とlen
関数 (長さ)がデフォルトで用意されている。両方とも引数にリストを取る。最後に float
型を str
型にキャスト(変換)してあげれば、完了。
もしくは、float
型のまま出力をしたい場合は、 print
関数の中全部を f{]
でFormatted stringに変更する。
print(f"Average: {sum(scores) / len(scores)}")
リストにデータを追加するためには、append
を使って実装可能。
from cs50 import get_int
scores = []
for i in range(3):
scores.append(get_int("Score: "))
...
文字列を全て大文字にするプログラムには、s.upper()
で指定可能だが、全ての文字を一つずつ操作することもできる。for c in s
で、文字列 S
を一つずつ c
でアクセスしている。
from cs50 import get_string
s = get_string("Before: ")
print("After: ", end="")
for c in s:
print(c.upper(), end="")
print()
コマンドライン引数、エグジット(Command-line arguments, exit codes)
コマンドラインから複数の引数を取るためには、sys
ライブラリーから argv
をインポートし、引数の数に応じて処理を実行できる。argv
はリストなので、argv[1]
と指定すれば、2つ目の引数にアクセスできる。よって、次のプログラムは、コマンドラインに python argv.py David
と入力すれば、hello, David
と出力される。
from sys import argv
if len(argv) == 2:
print(f"hello, {argv[1]}")
else:
print("hello, world")
また、次のプログラムを実行したら、コマンドラインにに入力した引数すべてが出力される。
from sys import argv
for arg in argv:
print(arg)
期待していた引数の数とは違う分だけ入力された場合の処理も可能。sys.exit()
関数は、main
から出ることを意味し、エラーコード(番号)と共に exit
する。
import sys
if len(sys.argv) != 2:
print("missing command-line argument")
sys.exit(1)
print(f"hello, {sys.argv[1]}")
sys.exit(0)
アルゴリズム(Algorithms)
線形探索も非常に簡単に実装できる。
import sys
numbers = [4, 6, 8, 2, 7, 5, 0]
if 0 in numbers:
print("Found")
sys.exit(0)
print("Not found")
sys.exit(1)
if 0 in numbers:
でリストの中身をすべて確認している。
文字列のリストも探索可能。
names = ["Bill", "Charlie", "Fred", "George", "Ginny", "Percy", "Ron"]
if "Ron" in names:
print("Found")
else:
print("Not found")
辞書型があれば、key
に対応する value
を返す。
from cs50 import get_string
people = {
"Brian": "+1-617-495-1000",
"David": "+1-949-468-2750"
}
name = get_string("Name: ")
if name in people:
print(f"Number: {people[name]}")
まず、people
の key
の名前に対応する value
電話番号を保存している。次に、if name in people:
で辞書の中身を名前で探索し、それに対する value
である 電話番号を返す。 C言語の配列のように people[name]
と指定できるが、[]
の中身は数字でなくても文字列でも指定できる。
2つの数値を入れ替えることも簡単にできる。C言語では、ポインタを使って実装する必要があったが… 実はPythonでは、ユーザがポインタを使って操作できないようになっているため、このような機能が備わっている。
x = 1
y = 2
print(f"x is {x}, y is {y}")
x, y = y, x
print(f"x is {x}, y is {y}")
ファイル(Files)
CSVファイルの操作をしてみよう。
import csv
from cs50 import get_string
file = open("phonebook.csv", "a")
name = get_string("Name: ")
number = get_string("Number: ")
writer = csv.writer(file)
writer.writerow([name, number])
file.close()
Python には、csv
ライブラリーも用意されていて、ファイルを開けた後は、csv.writer
関数を呼び、writer.writerow
を使って行を追加することができる。
with
を使えば、データ追加が終了した後、自動的にファイルを閉じてくれる。
...
with open("phonebook.csv", "a") as file:
writer = csv.writer(file)
writer.writerow((name, number))
Google formを使って集めたハリーポッターのデータを CSV ファイルにダウンロードし、操作する例も紹介された。
import csv
houses = {
"Gryffindor": 0,
"Hufflepuff": 0,
"Ravenclaw": 0,
"Slytherin": 0
}
with open("Sorting Hat (Responses) - Form Responses 1.csv", "r") as file:
reader = csv.reader(file)
next(reader)
for row in reader:
house = row[1]
houses[house] += 1
for house in houses:
print(f"{house}: {houses[house]}")
CSV
ライブラリーに用意されている reader
関数を使い、また、最初の行はヘッダーなので、 next (reader)
を使ってスキップする。2つ目の列に入っているデータ row[1]
にアクセスし、house
に代入し、辞書 houses
にデータを追加していく。
その他のライブラリー(More libraries)
文字の読みおこし(Text to speech)

ここから更にPython がパワフルになっていく。
import pyttsx3
engine = pyttsx3.init()
engine.say("hello, world")
engine.runAndWait()
engine.say(f"hello, {name}")
と指定してあげればユーザが入力した名前を読み上げてくれる。
import pyttsx3
engine = pyttsx3.init()
name = input("What's your name? ")
engine.say(f"hello, {name}")
engine.runAndWait()
顔認証(Facial recognition)

Pythonには、顔認証ライブラリー face_recognition
も用意されており、簡単に使うことができる。
# Find faces in picture
# https://github.com/ageitgey/face_recognition/blob/master/examples/find_faces_in_picture.py
from PIL import Image
import face_recognition
# Load the jpg file into a numpy array
image = face_recognition.load_image_file("office.jpg")
# Find all the faces in the image using the default HOG-based model.
# This method is fairly accurate, but not as accurate as the CNN model and not GPU accelerated.
# See also: find_faces_in_picture_cnn.py
face_locations = face_recognition.face_locations(image)
for face_location in face_locations:
# Print the location of each face in this image
top, right, bottom, left = face_location
# You can access the actual face itself like this:
face_image = image[top:bottom, left:right]
pil_image = Image.fromarray(face_image)
pil_image.show()
QRコードを作る

QRコードを生成するのも数行のコードで実装できる。qrcode
ライブラリー
import os
import qrcode
img = qrcode.make("https://youtu.be/oHg5SJYRHA0")
img.save("qr.png", "PNG")
os.system("open qr.png")
音声認識(Speech recognition)

speech_recognition
ライブラリーを使えば、マイクに話した内容をテキストに変換してくれる。
import speech_recognition
# Obtain audio from the microphone
recognizer = speech_recognition.Recognizer()
with speech_recognition.Microphone() as source:
print("Say something:")
audio = recognizer.listen(source)
# Recognize speech using Google Speech Recognition
print("You said:")
print(recognizer.recognize_google(audio))
これを少し応用すれば、会話をすることもできる。
...
words = recognizer.recognize_google(audio)
# Respond to speech
if "hello" in words:
print("Hello to you too!")
elif "how are you" in words:
print("I am well, thanks!")
elif "goodbye" in words:
print("Goodbye to you too!")
else:
print("Huh?")
感想

Artificial Intelligence (AI・人工知能)技術の需要がこれからもどんどん増えていくなかで、人工知能のプログラムを簡単に実装できるPythonを学ぶことはもはや必要不可欠に感じる。今回の講義では、Pythonの触りだけだったので、もう少し深堀りできる講義も受けてみようと思う。
未希 諒
Related posts
About media
Ramps Blog は、ノマドによるノマドのためのブログです。日本、香港、シンガポール、タイ、台湾のノマド生活を通じて見えた景色、特に食、カルチャー、テクノロジー、ビジネス、アート、デザインなどについて発信しています。
Recent Posts
Twitter feed is not available at the moment.