Notes

はじめに

  • これまで、HTMLとCSSを使って簡単なWebページを構築する方法を、そして、GitとGitHubを使ってコードの変更を追跡し、他の人と共同作業するための方法を説明してきました。
  • 今日は、このコースで使用する2つの主要なプログラミング言語のひとつであるPythonについて説明します。

Python

Python Logo
  • Pythonは非常に強力で広く使われている言語であり、非常に複雑なWebアプリケーションをすばやく構築することができます。このコースでは、Python 3を使用しますが、Python 2がまだ使用されている場合もあります。外部のリソースを調べる場合は、同じバージョンを使用していることを確認してください。
  • まず、多くのプログラミング言語で最初に行う「Hello, world」から始めましょう。このプログラムをPythonで書くと、次のようになります。
print("Hello, world!")
  • このコードで何が起こっているのかを説明していきましょう。Python言語に組み込まれた print 関数があります。この関数は括弧内の引数を受け取り、その引数をコマンドラインに表示します。
  • このプログラムを実際にコンピュータ上で記述して実行するには、まずこの行を任意のテキストエディタに入力し、ファイルを something.py として保存します。次に、ターミナルに移動し、ファイルが格納されているディレクトリーに移動して、python something.py と入力します。上記プログラムの場合、ターミナルに「Hello, world!」と表示されます。
  • コンピュータの設定によっては、ファイル名の前に python ではなく python3 と入力する必要があります。また、Pythonをまだダウンロードしていない場合は、ダウンロードする必要があります。Pythonをインストールしたら、Pipもダウンロードすることをお勧めします。これは、このコースの後半で必要になります。
  • ターミナルに python file.py と入力すると、Pythonと一緒にダウンロードしたインタプリタと呼ばれるプログラムがファイルを1行ずつ読み、コードの各行を実行します。これは、実行する前にマシンコードにコンパイルする必要があるCJavaなどの言語とは異なります。

変数

プログラミング言語の重要な部分は、変数を作成および操作する機能です。Pythonで変数に値を代入する構文は次のようになります。

a = 28
b = 1.5
c = "Hello!"
d = True
e = None

これらの各行は、= の右側の値を取得し、左側の変数名に格納します。

他のプログラミング言語とは異なり、Pythonの変数型は推測されます。つまり、各変数には型がありますが、変数を作成するときにどの型であるかを明示的に指定する必要はありません。最も一般的な変数タイプは次のとおりです。

  • int:整数
  • float:実数
  • chr:文字
  • str:文字列 (文字のシーケンス)
  • boolTrue または False のいずれかの値
  • NoneType:値がない (None) ことを示す特別な値

次に、ユーザからの入力を受け取り、そのユーザに挨拶できる、より興味深いプログラムの作成に取り組みます。これを行うには、input という別の組み込み関数を使用します。この関数は、ユーザにプロンプトを表示し、ユーザが入力として指定した内容を返します。たとえば、name.py というファイルに次のように記述できます。

name = input("Name: ")
print("Hello, " + name)

ターミナル上で実行すると、プログラムは次のようになります。

Hello

ここで注意すべき点がいくつかあります。

  • 最初の行では、変数名を明示的な値に割り当てるのではなく、input 関数が返す値に変数名を割り当てます。
  • 2行目では、+ 演算子を使用して2つの文字列を結合 (連結) しています。Pythonでは、+ 演算子を使用して数値を加算(足し算)したり、文字列とリストを連結したりできます。

文字列フォーマット

  • 上で説明したように、+ 演算子を使用して文字列を結合することもできますが、最新バージョンのPythonでは、さらに簡単に文字列を操作する方法があり、フォーマット済文字列 (f-strings) と呼ばれます。
  • フォーマット済文字列を使用していることを示すには、引用符の前に f を追加します。例えば、上で行ったように "Hello, " + name を使用する代わりに、同じ結果に対して f"Hello, {name}" と書くことができます。必要に応じて、この文字列に関数を接続し、上のプログラムを1行にすることもできます。
print(f"Hello, {input("Name: ")}")

条件

  • 他のプログラミング言語と同様に、Pythonは異なる条件に基づいて異なるコードを実行する機能を提供します。たとえば、次のプログラムでは、ユーザが入力する数値に応じて出力を変更します。
num = input("Number: ")
if num > 0:
    print("Number is positive")
elif num < 0:
    print("Number is negative")
else:
    print("Number is 0")
  • 上記のプログラムがどのように動作するかを見てみると、Pythonの条件式には、キーワード( ifelif ,または else )に続いて( else の場合を除いて)ブール式、あるいは TrueFalse のいずれかに評価される式が含まれています。次に、特定の式が true の場合に実行するすべてのコードが、ステートメントのすぐ下にインデントされます。インデントはPython構文の一部として必要です。
  • しかし、このプログラムを実行すると、次のような例外が発生します。
condition
  • 例外は、Pythonコードの実行中にエラーが発生した場合に発生します。経験を積むにしたがって、エラーを解釈するスキルが向上するはずです。これは、非常に役立つスキルです。
  • この特定の例外をもう少し詳しく見てみましょう。一番下を見ると、TypeError が発生しています。これは一般的に、Pythonは特定の変数がある型であることを予想していましたが、それが別の型であることに気付きましたという意味です。この場合、例外は、str と int を比較するために > 記号を使用できないことを示しています。上記では、この比較が2行目で行われていることがわかります。
  • この場合、0 が整数であることは明らかなので、num 変数が文字列である必要があります。これは、input 関数が常に文字列を返すことが判明し、int 関数を使用して整数に変換(キャスト)するように指定する必要があるためです。つまり、最初の行は次のようになります。
num = int(input("Number: "))
  • これで、プログラムは意図したとおりに動作します。

シーケンス

Python言語の最も強力な部分の1つは、個々の変数に加えてデータのシーケンスを操作できることです。

いくつかの点では似ていますが、異なった種類のシーケンスがあります。これらの違いを説明する際には、mutable/immutable (変更可能/変更不可)およびordered/unordered (順序あり/順序なし) という用語を使用します。Mutableとはシーケンスが定義されると、そのシーケンスの個々の要素が変更できることを意味し、orderedはオブジェクトの順序が意味を持つことを表します。

文字列

: Ordered: はい
Mutable: いいえ

文字列についてはすでに少し説明しましたが、単なる変数ではなく、文字列を文字のシーケンスと考えることができます。これは、文字列内の個々の要素にアクセスできることを意味します。たとえば、次のようになります。

name = "Harry"
print(name[0])
print(name[1])

このプログラムは文字列の最初の (インデックス0の) 文字(つまり H )を出力し、次に2番目の (インデックス1の) 文字(つまり a )を出力します。

リスト

: Ordered: はい
Mutable: はい

Pythonリストを使用すると、どんな型の変数でも格納できます。次に示すように、角括弧とカンマを使用してリストを作成します。文字列と同様に、リスト全体を出力することも、個別の要素を出力することもできます。append を使ってリストに要素を追加したり、sort を使ってリストをソートしたりすることもできます。

# This is a Python comment
names = ["Harry", "Ron", "Hermione"]
# Print the entire list:
print(names)
# Print the second element of the list:
print(names[1])
# Add a new name to the list:
names.append("Draco")
# Sort the list:
names.sort()
# Print the new list:
print(names)
Names

タプル

: Ordered: はい
Mutable: いいえ

タプルは、通常、点のx値とy値など、いくつかの値を一緒に格納する必要がある場合に使用されます。Pythonコードでは、括弧を使用します。

point = (12.5, 10.6)

集合

: Ordered: いいえ
Mutable: (該当なし)

セットは、順序がないという点でリストやタプルとは異なります。また、リスト・タプル内には同じ要素を2つ以上持つことができますが、セットはそれぞれの値を1度しか格納しません。set 関数を使用して空のセットを定義できます。次に、addremove を使用してそのセットに要素を追加し、removeを使用してそのセットから要素を削除し、len 関数を使用してセットのサイズを調べます。len関数はPythonのすべてのシーケンスで動作することに注意してください。また、セットに 43 を2回追加しても、各項目は1つのセットに1回しか表示されません。

# Create an empty set:
s = set()

# Add some elements:
s.add(1)
s.add(2)
s.add(3)
s.add(4)
s.add(3)
s.add(1)

# Remove 2 from the set
s.remove(2)

# Print the set:
print(s)

# Find the size of the set:
print(f"The set has {len(s)} elements.")

""" This is a python multi-line comment:
Output:
{1, 3, 4}
The set has 3 elements.
"""

辞書型

: Ordered: いいえ
Mutable: はい

このコースでは、Pythonの辞書型 dict が特に役立ちます。辞書はキーと値のペアのセットで、各キーには対応する値があります。辞書と同様に、各単語(キー)には対応する定義(値)があります。Pythonでは、中括弧を使用して辞書を表し、コロンを使用してキーと値を示します。たとえば、次のようになります。

# Define a dictionary
houses = {"Harry": "Gryffindor", "Draco": "Slytherin"}
# Print out Harry's house
print(houses["Harry"])
# Adding values to a dictionary:
houses["Hermione"] = "Gryffindor"
# Print out Hermione's House:
print(houses["Hermione"])

""" Output:
Gryffindor
Gryffindor
"""

ループ

ループは、あらゆるプログラミング言語の中で非常に重要な部分であり、Pythonでは、forループwhileループ という2つの主要な形式があります。ここでは、forループについて説明します。

  • forループは、要素のシーケンスを反復するために使用され、配列内の各要素に対してコードのブロック(下にインデントされる)を実行します。たとえば、次のコードは0~5の数値を出力します。
for i in [0, 1, 2, 3, 4, 5]:
    print(i)

""" Output:
0
1
2
3
4
5
"""
  • python の range 関数を使用すると、このコードを短縮することができ、一連の数値を簡単に取得することができます。次のコードは、上記のコードとまったく同じ結果になります。
for i in range(6):
    print(i)

""" Output:
0
1
2
3
4
5
"""
  • このタイプのループは、どのシーケンスでも機能します。たとえば、それぞれの名前をリストに出力する場合は、次のコードを記述します。
# Create a list:
names = ["Harry", "Ron", "Hermione"]

# Print each name:
for name in names:
    print(name)

""" Output:
Harry
Ron
Hermione
"""
  • 必要に応じてさらに詳細に指定し、1つの名前の各文字をループします。
name = "Harry"
for char in name:
    print(char)

""" Output:
H
a
r
r
y
"""

関数

すでに printinput などのPython関数をいくつか見てきましたが、今度は独自の関数を作成する方法について説明します。最初に、数値を取り込んで2乗する関数を作成します。

def square(x):
    return x * x

def キーワードを使用して関数を定義すること、x という1つの入力を取り込むこと、return キーワードを使用して関数の出力を示すことに注意してください。

他の関数と同じように、括弧を使用してこの関数を 「呼び出す」 ことができます。

for i in range(10):
    print(f"The square of {i} is {square(i)}")

""" Output:
The square of 0 is 0
The square of 1 is 1
The square of 2 is 4
The square of 3 is 9
The square of 4 is 16
The square of 5 is 25
The square of 6 is 36
The square of 7 is 49
The square of 8 is 64
The square of 9 is 81
"""

モジュール

プロジェクトの規模が大きくなった場合、1つのファイルに関数を記述し、それを別のファイルで実行できるようになると便利です。上記の例では、functions.py という1つのファイルを以下のコードで作成します。

def square(x):
    return x * x

square.py という別のファイルがあります。

for i in range(10):
    print(f"The square of {i} is {square(i)}")

しかし、square.py を実行しようとすると、次のエラーが発生します。

Name Error

この問題が発生するのは、デフォルトではPythonファイルは互いを認識しないため、先ほど作成した functions モジュールから square 関数を明示的に import する必要があるためです。square.py は次のようになります。

from functions import square

for i in range(10):
    print(f"The square of {i} is {square(i)}")

あるいは、functions モジュール全体をインポートし、ドット表記を使用して square 関数にアクセスすることもできます。

import functions

for i in range(10):
    print(f"The square of {i} is {functions.square(i)}")

インポートできる組み込みPythonモジュールには、mathcsv など、さらに多くの関数へのアクセスを可能にする多くのものがあります。さらに、より多くのモジュールをダウンロードして、より多くの機能にアクセスできます。Django モジュールの使用には多くの時間を割きますが、これについては次のレッスンで説明します。

オブジェクト指向プログラミング

オブジェクト指向プログラミングは、情報を格納してアクションを実行できるオブジェクトを中心としたプログラミングのパラダイム、またはプログラミングについての考え方です。

  • クラス:Pythonではすでにいくつかの異なる型の変数を見てきましたが、独自の型を作成したい場合はどうすればよいでしょうか。Pythonのクラスは基本的に、情報を格納してアクションを実行できる新しいタイプのオブジェクトのテンプレートです。以下に、2次元の点を定義するクラスを示します。
class Point():
    # A method defining how to create a point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
  • 上記のコードでは、キーワード self を使用して、現在作業中のオブジェクトを表しています。Pythonクラス内のメソッドの最初の引数は self でなければなりません。

では、上のクラスを実際に使用してオブジェクトを作成する方法を見てみましょう。

p = Point(2, 8)
print(p.x)
print(p.y)

""" Output:
2
8
"""

次に、点(Point)の座標だけを保存するのではなく、航空便を表すクラスを作成して、より興味深い例を見てみましょう。

class Flight():
    # Method to create new flight with given capacity
    def __init__(self, capacity):
        self.capacity = capacity
        self.passengers = []

    # Method to add a passenger to the flight:
    def add_passenger(self, name):
        self.passengers.append(name)

しかし、定員を決めても定員が増えすぎてしまう可能性があるため、このクラスには欠陥があります。乗客を追加する前に、フライトに空きがあるかどうかを確認するように、この機能を拡張します。

class Flight():
    # Method to create new flight with given capacity
    def __init__(self, capacity):
        self.capacity = capacity
        self.passengers = []

    # Method to add a passenger to the flight:
    def add_passenger(self, name):
        if not self.open_seats():
            return False
        self.passengers.append(name)
        return True

    # Method to return number of open seats
    def open_seats(self):
        return self.capacity - len(self.passengers)

上記では、空席があるかどうかを判断するために、if not self.open_seats() の行を使用しています。これが機能するのは、Pythonでは数字の0が False を意味すると解釈されるためです。また、not キーワードを使用して、次のステートメントの反対を意味しないようにすることもできます。したがって、not TrueがFalseとなり、not FalseTrue となります。したがって、open_seats が0を返した場合、式全体が True と評価されます。

ここで、いくつかのオブジェクトをインスタンス化して作成したクラスを試してみましょう。

# Create a new flight with o=up to 3 passengers
flight = Flight(3)

# Create a list of people
people = ["Harry", "Ron", "Hermione", "Ginny"]

# Attempt to add each person in the list to a flight
for person in people:
    if flight.add_passenger(person):
        print(f"Added {person} to flight successfully")
    else:
        print(f"No available seats for {person}")

""" Output:
Added Harry to flight successfully
Added Ron to flight successfully
Added Hermione to flight successfully
No available seats for Ginny
"""

関数型プログラミング

オブジェクト指向プログラミングのサポートに加えて、Pythonは、関数が他の変数と同じように値として扱われる関数型のプログラミングパラダイムもサポートしています。

デコレータ

関数型プログラミングによって可能になることの1つは、別の関数を変更できるという高次関数であるデコレータの概念です。例えば、関数がいつ開始され、いつ終了するかを通知するデコレータを作成します。その後、@ 記号を使用してデコレータを適用できます。

def announce(f):
    def wrapper():
        print("About to run the function")
        f()
        print("Done with the function")
    return wrapper

@announce
def hello():
    print("Hello, world!")

hello()

""" Output:
About to run the function
Hello, world!
Done with the function
"""

ラムダ関数

ラムダ関数は、Pythonで関数を作成するもう1つの方法です。たとえば、先ほどと同じ square 関数を定義する場合は、次のように記述できます。

square = lambda x: x * x

ここで、入力は : の左側、出力は右側です。

これは、単一の小さな関数を作ればよく、完全に別個の関数を作成するほどではない場合に便利です。たとえば、最初はソート方法が明確でないオブジェクトをソートする場合などです。人のリストがあって、ソートしたい名前だけでなく名前と家があるとします。

people = [
    {"name": "Harry", "house": "Gryffindor"},
    {"name": "Cho", "house": "Ravenclaw"},
    {"name": "Draco", "house": "Slytherin"}
]

people.sort()

print(people)

しかし、この場合は次のようなエラーになります。

Type Error

これは、Pythonが2つの辞書を比較して一方が他方より小さいかどうかをチェックする方法を知らないために起こります。

この問題を解決するには、並べ替えに使用する辞書の部分を指定するsort関数に key 引数を含めます。

people = [
    {"name": "Harry", "house": "Gryffindor"},
    {"name": "Cho", "house": "Ravenclaw"},
    {"name": "Draco", "house": "Slytherin"}
]

def f(person):
    return person["name"]

people.sort(key=f)

print(people)

""" Output:
[{'name': 'Cho', 'house': 'Ravenclaw'}, {'name': 'Draco', 'house': 'Slytherin'}, {'name': 'Harry', 'house': 'Gryffindor'}]
"""

これは機能しますが、1回しか使用しない関数全体を記述する必要がありました。ラムダ関数を使用することで、コードをより読みやすくすることができます。

people = [
    {"name": "Harry", "house": "Gryffindor"},
    {"name": "Cho", "house": "Ravenclaw"},
    {"name": "Draco", "house": "Slytherin"}
]

people.sort(key=lambda person: person["name"])

print(people)

""" Output:
[{'name': 'Cho', 'house': 'Ravenclaw'}, {'name': 'Draco', 'house': 'Slytherin'}, {'name': 'Harry', 'house': 'Gryffindor'}]
"""

例外

この講義では、いくつかの異なる例外に遭遇しました。ここでは、それらの例外に対処する新しい方法について説明します。

次のコードでは、ユーザから2つの整数を取得し、それらを除算します。

x = int(input("x: "))
y = int(input("y: "))

result = x / y

print(f"{x} / {y} = {result}")

多くの場合、このプログラムは正常に動作します。

Good example

ただし、0で除算しようとすると問題が発生します。

Bad example

この面倒なエラーは、例外処理を使用して処理できます。次のコードブロックでは、ZeroDivisionError が返された場合を除き、2つの数値を除算しようとします。

import sys

x = int(input("x: "))
y = int(input("y: "))

try:
    result = x / y
except ZeroDivisionError:
    print("Error: Cannot divide by 0.")
    # Exit the program
    sys.exit(1)

print(f"{x} / {y} = {result}")

この場合、もう一度実行すると、次のようになります。

Divide by 0 exception

ただし、ユーザが x と y に数値以外を入力すると、エラーが発生します。

Value error

同じような方法でこの問題を解決できます!

import sys

try:
    x = int(input("x: "))
    y = int(input("y: "))
except ValueError:
    print("Error: Invalid input")
    sys.exit(1)

try:
    result = x / y
except ZeroDivisionError:
    print("Error: Cannot divide by 0.")
    # Exit the program
    sys.exit(1)

print(f"{x} / {y} = {result}")

これでこのレッスンは終わりです!次回は、Pythonの Django モジュールを使っていくつかのアプリケーションを構築します。