Pythonの基本データ型と制御構造

変数

Pythonでは変数の宣言は不要です。値を代入すると、その変数オブジェクトが自動的に生成されます。

オブジェクトへの参照を削除するにはdel文を使用します。

不変データ型とは、データの値を変更すると新しいメモリ領域が割り当てられることを意味します。変数のアドレスはid()関数で確認できます。

  • 不変データ型: 数値(Number)、文字列(String)、タプル(Tuple)
  • 可変データ型: リスト(List)、セット(Set)、辞書(Dictionary)

文字列、リスト、タプルはすべてシーケンス(sequence)に属します。

変数の型はtype()で、型の一致はisinstance()で確認できます。

>>> class A:
...     pass
... 
>>> class B(A):
...     pass
... 
>>> isinstance(A(), A)
True
>>> type(A()) == A 
True
>>> isinstance(B(), A)
True
>>> type(B()) == A
False

数値型 (Number)

Pythonの数値型には整数(int)、浮動小数点数(float)、ブール値(bool)、複素数(complex)があります。

浮動小数点数は科学記数法で表現できます。例えば、2.5e22.5 x 10^2、つまり250を意味します。

浮動小数点数は8進数や16進数でも表現できます。

>>> 10 - 4  # 減算
6
>>> 3 * 7  # 乗算
21
>>> 15 / 3  # 除算(結果は浮動小数点数)
5.0
>>> 17 // 4 # 除算(結果は切り捨ての整数)
4
>>> 17 % 5 # 剰余
2
>>> 2 ** 4 # 累乗
16

int()float()などの関数で、他の型を数値型に変換できます。

文字列 (String)

文字列はシングルクォート(')またはダブルクォート(")で囲みます。バックスラッシュ(\)でエスケープします。

文字列は不変です。特定の位置に直接代入することはできず、文字列全体を再代入する必要があります。

文字列のスライス(部分取り出し)は、変数[開始インデックス:終了インデックス]で行います。インデックスは0から始まり、-1が最後の要素を指します。

text = 'HelloWorld'

print(text)          # 文字列全体を出力
print(text[0:-1])    # 最初から最後の一つ前までの文字を出力
print(text[0])       # 最初の文字を出力
print(text[2:5])     # 3文字目から5文字目までを出力
print(text[2:])      # 3文字目から最後までを出力
print(text * 2)      # 文字列を2回繰り返す
print(text + " TEST") # 文字列を連結する

HelloWorld
HelloWorl
H
llo
lloWorld
HelloWorldHelloWorld
HelloWorld TEST

f-stringはPython 3.6で導入された機能です。文字列の前にfを付け、中括弧{}で変数や式を埋め込めます。

>>> name = 'Alice'
>>> f'こんにちは、{name}さん'  # 変数の置換
'こんにちは、Aliceさん'
>>> f'{2+3}'         # 式の評価
'5'

>>> user = {'name': 'Bob', 'age': 30}
>>> f'{user["name"]}は{user["age"]}歳です'
'Bobは30歳です'

Python 3.8以降、式とその結果を=で結合して表示できます。

>>> x = 5
>>> print(f'{x+1}')   # Python 3.6
6

>>> x = 5
>>> print(f'{x+1=}')   # Python 3.8
'x+1=6'

Pythonの文字列には多くの組み込みメソッドがあります。

番号 メソッドと説明
1 capitalize() 文字列の最初の文字を大文字に変換します。
2 center(width, fillchar) 指定された幅widthで中央揃えされた文字列を返します。fillcharは埋める文字で、デフォルトはスペースです。
3 count(str, beg=0, end=len(string)) strstring内に現れる回数を返します。begendが指定されると、指定された範囲内での出現回数を返します。
4 encode(encoding='UTF-8', errors='strict') 指定されたエンコーディングで文字列をエンコードします。エラーが発生した場合、デフォルトではValueError例外が発生します。
5 endswith(suffix, beg=0, end=len(string)) 文字列がsuffixで終わるかどうかをチェックします。指定された範囲内でチェックする場合は、begendを指定します。
6 find(str, beg=0, end=len(string)) strが文字列に含まれているか検索します。含まれていれば開始インデックスを、含まれていなければ-1を返します。
7 index(str, beg=0, end=len(string)) find()と似ていますが、strが見つからない場合に例外を発生させます。
8 isalnum() 文字列が少なくとも一文字を持ち、すべての文字が英数字である場合にTrueを返します。
9 isalpha() 文字列が少なくとも一文字を持ち、すべての文字がアルファベットである場合にTrueを返します。
10 isdigit() 文字列が数字のみで構成されている場合にTrueを返します。
11 islower() 文字列に少なくとも一つの大文字小文字を区別する文字が含まれ、すべてが小文字である場合にTrueを返します。
12 isnumeric() 文字列が数字文字のみで構成されている場合にTrueを返します。
13 isspace() 文字列が空白文字のみで構成されている場合にTrueを返します。
14 join(seq) 指定された文字列を区切り文字として、seq内のすべての要素を連結した新しい文字列を返します。
15 len(string) 文字列の長さを返します。
16 lower() 文字列内のすべての大文字を小文字に変換します。
17 lstrip() 文字列の左側の空白または指定された文字を削除します。
18 replace(old, new[, max]) 文字列内のoldnewに置換します。maxが指定されると、置換はmax回まで行われます。
19 split(str="", num=string.count(str)) strを区切り文字として文字列を分割します。numが指定されると、分割はnum+1個の部分文字列で行われます。
20 startswith(substr, beg=0, end=len(string)) 文字列がsubstrで始まるかどうかをチェックします。
21 strip([chars]) 文字列の両端の空白または指定された文字を削除します。
22 upper() 文字列内のすべての小文字を大文字に変換します。

リスト (List)

リストは角括弧[]で定義され、カンマで区切られた要素(数値、文字列、リストなど)を含みます。ネストや混在も可能です。

操作は文字列と似ていますが、リスト内の要素は変更可能です。

>>> numbers = [10, 20, 30, 40, 50]
>>> numbers[0] = 99
>>> numbers[2:5] = [13, 14, 15]
>>> numbers
[99, 20, 13, 14, 15, 50]
>>> numbers[2:5] = []   # 指定範囲の要素を空リストで置き換える
>>> numbers
[99, 20, 50]
>>> sliced = numbers[0::2] # [開始:終了:ステップ] ステップは何個おきに要素を取るかを指定します
>>> sliced
[99, 50]
>>> numbers + sliced # +演算子で連結
[99, 20, 50, 99, 50]

split()join()はJavaScriptと同様の使い方ができます。

del文でリストの要素を削除できます。

ネストされたリスト:

>>> letters = ['a', 'b', 'c']
>>> nums = [1, 2, 3]
>>> nested = [letters, nums]
>>> nested
[['a', 'b', 'c'], [1, 2, 3]]
>>> nested[0]
['a', 'b', 'c']
>>> nested[0][1]
'b'
番号 メソッド
1 append(obj) リストの末尾に新しいオブジェクトを追加します。
2 count(obj) 指定された要素がリスト内に現れる回数を返します。
3 extend(seq) リストの末尾に、別のシーケンスのすべての要素を追加します。
4 index(obj) 指定された値が最初に現れるインデックスを返します。
5 insert(index, obj) 指定されたインデックスにオブジェクトを挿入します。
6 pop([index=-1]) リストから要素を削除(デフォルトは最後の要素)し、その値を返します。
7 remove(obj) 指定された値の最初の出現をリストから削除します。
8 reverse() リストの要素を逆順にします。
9 sort(key=None, reverse=False) リストをソートします。
10 clear() リストを空にします。
11 copy() リストの浅いコピーを返します。

リストはスタック(append()pop())やキューとして便利に使えます。

リスト内包表記:

values = [1, 3, 5, 7]
[[x, x**3] for x in values if x > 2]
# [[3, 27], [5, 125], [7, 343]]

タプル (Tuple)

タプルはリストと似ていますが、要素を変更できない点が異なります。

丸括弧()で定義します。要素が2つ以上の場合、括弧は省略できます。

タプルは+演算子で連結できます。

インデックスを使ってスライスや組み合わせができます。

全体のタプルはdelで削除できますが、個々の要素は削除できません。

空のタプルや単一要素のタプルを作成するには特別な構文が必要です。

empty_tuple = ()    # 空のタプル
single_tuple = (42,) # 単一要素のタプルにはカンマが必要

セット (Set)

セットは、順序がなく、重複要素のないコレクションです。

メンバーシップテストや重複要素の削除に使用されます。

{...}またはset()で作成できます。

空のセットを作成するにはset()を使用する必要があります。なぜなら{}は空の辞書を作成するためです。

brands = {'Apple', 'Google', 'Microsoft', 'Apple', 'Amazon'}
print(brands)   # 重複した要素は自動的に削除される
# {'Google', 'Microsoft', 'Apple', 'Amazon'}

# メンバーシップテスト
if 'Apple' in brands:
    print('Appleはセットに含まれています')
else:
    print('Appleはセットに含まれていません')
# Appleはセットに含まれています

# セットの演算
set_a = set('abracadabra')
set_b = set('alacazam')

print(set_a)
# {'b', 'c', 'a', 'r', 'd'}
print(set_a - set_b)     # 差集合
# {'r', 'b', 'd'}
print(set_a | set_b)     # 和集合
# {'b', 'c', 'a', 'z', 'm', 'r', 'l', 'd'}
print(set_a & set_b)     # 積集合
# {'c', 'a'}
print(set_a ^ set_b)     # 対称差集合
# {'z', 'b', 'm', 'r', 'l', 'd'}
メソッド 説明
add() セットに要素を追加します。
clear() セットからすべての要素を削除します。
copy() セットのコピーを返します。
difference() 複数のセットの差集合を返します。
discard() セットから指定された要素を削除します。
intersection() セットの積集合を返します。
pop() セットからランダムな要素を削除して返します。
remove() セットから指定された要素を削除します。
union() セットの和集合を返します。
update() セットに要素を追加します。

辞書 (Dictionary)

辞書は中括弧{}で定義され、キーと値のペアで構成されます。キーは不変型でなければならず、一意である必要があります。同じキーで値を再代入すると、後の値が前の値を上書きします。

info = {}
info['name'] = "Taro"
info[2] = "Two"

data = {'name': 'Jiro', 3.14: 1, 2: 'www.example.com'}

print(data['name'])       # キー'name'の値を出力
print(data[2])           # キー2の値を出力
print(data)          # 辞書全体を出力
print(data.keys())   # すべてのキーを出力
print(data.values()) # すべての値を出力

del data['name'] # キー'name'を削除
data.clear()     # 辞書をクリア
del data         # 辞書を削除

# キーと値のペアのリストから辞書を作成
dict([('key1', 1), ('key2', 2)])
# {'key1': 1, 'key2': 2}

# キーワード引数から辞書を作成
dict(key1=1, key2=2)
# {'key1': 1, 'key2': 2}

# 辞書内包表記
{x: x**3 for x in (1, 2, 3)}
# {1: 1, 2: 8, 3: 27}

演算子

単行コメントは#で記述します。複数行コメントは'''または"""で囲みます。

:=(ウォルラス演算子)は、式の中で変数に値を代入できるPython 3.8で追加された機能です。

ビットシフト演算子(左シフトは2のべき乗乗算、右シフトは2のべき乗除算)。

論理演算子: and, or, not

メンバーシップ演算子: in, not in

同一性演算子: is, is not

isは、2つの識別子が同じオブジェクトを参照しているか(同じメモリアドレスか)を判断します。==は、変数の値が等しいかを判断します。

>>> a = [1, 2, 3]
>>> b = a
>>> b is a 
True
>>> b == a
True
>>> b = a[:]
>>> b is a
False
>>> b == a
True

Pythonはパフォーマンス向上のために、頻繁に使用される整数オブジェクト(-5から256まで)をキャッシュしています。これらの範囲内の整数は、プログラムのライフサイクル中、常に同じオブジェクトを参照します。

x = 10
y = 10
x is y		# True

x = 257
y = 257
x is y		# False

ただし、例外もあります。Pythonのプログラムは、コードブロック(モジュール、関数、クラス、インタラクティブシェルの単一行)を最小単位として実行します。同じコードブロック内の不変オブジェクトは、値が同じであれば、新しいオブジェクトを再作成せずに既存のオブジェクトを参照します。

z = 257
def check_value():
    a = 257
    b = 257
    print(a is b) # True
    print(a is z) # False

check_value()

結論:

  • 小整数オブジェクト(-5から256)は、グローバルインタープリタの範囲で再利用され、GCで解放されることはありません。
  • 同じコードブロック内の不変オブジェクトは、値が等しければ、新しいオブジェクトを再作成しません。
  • 文字列の場合、長さが20文字以内であればメモリアドレスは同じですが、21文字以上になると異なります。
  • 同じ.pyファイル内で、内容が同じであればメモリアドレスは同じです。

条件分岐: if

if 条件式:
    # 処理
elif 条件式:
    # 処理
else:
    # 処理

インデントでコードブロックを区切ります。他の言語の波括弧{}に相当します。

switch-case文はありません。

ループ

無限ループは、サーバーでのクライアントからのリアルタイムリクエスト処理に役立ちます。

while-elseでは、条件がFalseになった時にelseブロックが実行されますが、breakでループを抜けた場合は実行されません。

for-inは文字列でも使え、各文字が個別の文字列としてループされます。

TrueFalse10で代用できます。

breakcontinueがあります。インデントが必要です。

passは、プログラムの構造を保つための空のステートメントです。

count = 0
while count < 5:
   print (count, " は 5 未満")
   count = count + 1
else:
   print (count, " は 5 以上")

fruits = ["Apple", "Banana", "Cherry"]
for fruit in fruits:
    if fruit == "Banana":
        print("バナナが見つかりました!")
        break
    print("フルーツ: " + fruit)
else:
    print("フルーツは見つかりませんでした!")
print("ループ終了")

"""
フルーツ: Apple
フルーツ: Banana
バナナが見つかりました!
ループ終了
"""

for i in range(5):  # range(終了), range(開始, 終了, ステップ) で数値のシーケンスを生成
    print(i)

# range()とlen()を組み合わせてシーケンスのインデックスをループ
items = ['pen', 'notebook', 'eraser', 'ruler', 'pencil']
for i in range(len(items)):
    print(i, items[i])

# 辞書をループする(items()でキーと値のペアを取得)
for key, value in data.items():
    print(key, value)

# シーケンスをループする(enumerate()でインデックスと値を取得)
for i, v in enumerate(['one', 'two', 'three']):
    print(i, v)

# 複数のシーケンスを同時にループ(zip())
for a, b in zip(items, numbers):
    print(f'{a} の値は {b} です。')

# シーケンスを逆順にループ
for i in reversed(range(10)):
    print(i)

# シーケンスをソートしてループ
for f in sorted(set(data)):
    print(f)

イテレータ

イテレータは、コレクションの要素にアクセスする方法で、現在の位置を記憶します。

文字列、リスト、タプルなどで使用できます。

主なメソッドはiter()next()です。

data_list = [10, 20, 30, 40]
it = iter(data_list)
print(next(it))

イテレータはnext()で次の要素を取得でき、for-inループでも使用できます。

クラスをイテレータにするには、2つのメソッドを実装する必要があります。

class MyIterator:
  def __iter__(self):
    self.current = 0
    return self
 
  def __next__(self):
    if self.current < 5:
      value = self.current
      self.current += 1
      return value
    else:
      raise StopIteration

my_iter = MyIterator()
iter_obj = iter(my_iter)
 
print(next(iter_obj))
print(next(iter_obj))
print(next(iter_obj))

StopIteration例外は、イテレーションの終了を示します。

ジェネレータ

yieldキーワードを使用する関数はジェネレータと呼ばれます。ジェネレータは、反復可能な関数を返す関数、または特殊なイテレータです。

ジェネレータはyieldに到達すると、現在の実行状態を保存して一時停止し、yieldの値を返します。次にnext()が呼ばれると、一時停止した位置から実行を再開します。

def fibonacci_generator(n):
    a, b = 0, 1
    count = 0
    while True:
        if count > n:
            return
        yield a
        a, b = b, a + b
        count += 1

関数

def max_value(x, y):
    if x > y:
        return x
    else:
        return y

関数の引数渡し:

  • 不変型はC++の値渡しに似ており、関数内で変更しても外部の変数に影響しません。
  • 可変型は参照渡しに似ており、関数内で変更すると外部の変数も影響を受けます。

キーワード引数を使用すると、関数呼び出し時の引数の順序を宣言時と異ならせることができます。Pythonインタープリタは、パラメータ名で値をマッチングします。

関数宣言時にデフォルト値を設定できます。

可変長引数: *argsはタプルとして、**kwargsは辞書として受け取ります。

def show_info(arg1, **kwargs):
   print (arg1)
   print (kwargs)

show_info(1, name="Alice", age=30)

"""
1
{'name': 'Alice', 'age': 30}
"""

lambdaは無名関数で、簡単なロジックをカプセル化するのに便利です。

multiply = lambda x, y: x * y

print("掛け算の結果:", multiply(5, 6))

モジュール

モジュールは.pyファイルです。他のファイルから使用するには、ファイルの先頭でimport モジュール名と記述します。

同名のモジュールは、検索パスで最初に見つかったものだけがインポートされます。

デフォルトの検索パスにないモジュールは、sys.pathを変更してインポートできます。

モジュールの関数にローカルな名前を付けることができます: fib = fibo.fib

from モジュール名 import 関数名/変数名で、モジュール内の特定の関数や変数をインポートできます。カンマで区切って複数指定できます。これにより、インポートした名前が現在の名前空間に直接配置され、修飾なしで使用できます。すべての名前をインポートするには*を使用できますが、推奨されません。

モジュールには関数だけでなく、実行可能なコードも含まれます。モジュールが初めてインポートされたときに実行され、その中の変数はモジュール内のグローバル変数として機能し、他のモジュールに影響を与えません。

各モジュールには__name__属性があり、その値が'__main__'の場合、モジュール自身が実行されていることを示します。それ以外の場合は、他のモジュールからインポートされたことを示します。この属性を使って、プログラムブロックが他の関数からインポートされた場合に実行されないようにできます。

# Filename: module_example.py
if __name__ == '__main__':
   print('このモジュールは直接実行されています')
else:
   print('このモジュールはインポートされました')
   
# $ python module_example.py
# このモジュールは直接実行されています

# $ python
# >>> import module_example
# このモジュールはインポートされました

dir()は、モジュール内で定義されたすべての名前を文字列のリストとして返します。

パッケージ

パッケージはモジュールを管理する形式です。パッケージ.モジュールのようにアクセスします。

異なるパッケージ間でモジュール名が重複しても問題ありません。

ディレクトリに__init__.pyが含まれている場合、そのディレクトリはパッケージと見なされます。パッケージの初期化に使用できます。

Windowsプラットフォームでは大文字小文字を区別しないため、パッケージのインポートは正確に行う必要があります。

インポート方法はモジュールと同じですが、*の場合、__init__.py__all__リスト変数が存在する場合、そのリスト内のすべてのモジュールがインポートされます。それ以外の場合、何もインポートされません。

from-import方式のインポートが推奨されます。

相対パスを使ってパッケージをインポートできます。

入出力

出力

s = 'こんにちは'
print(s)
print(str(s))
print(repr(s))
print('{}サイト: "{}!"'.format('URL', 'www.example.com'))

"""
こんにちは
こんにちは
'こんにちは'
URLサイト: "www.example.com!"
"""

入力

input()は、ユーザーが入力した1行のテキストを読み取ります。

open(file, mode)はファイルオブジェクトを返します。modeはファイルを開くモードです。

モード 説明
r 読み取り専用モードでファイルを開きます。ファイルポインタはファイルの先頭に配置されます。(デフォルト)
w 書き込み専用モードでファイルを開きます。ファイルが存在する場合は、ファイルの先頭から編集され、既存の内容が削除されます。ファイルが存在しない場合は、新しいファイルが作成されます。
a 追記モードでファイルを開きます。ファイルが存在する場合は、ファイルポインタはファイルの末尾に配置され、新しい内容は既存の内容の後に書き込まれます。ファイルが存在しない場合は、新しいファイルが作成されます。
r+ 読み書きモードでファイルを開きます。ファイルポインタはファイルの先頭に配置されます。
w+ 読み書きモードでファイルを開きます。ファイルが存在する場合は、ファイルの先頭から編集され、既存の内容が削除されます。ファイルが存在しない場合は、新しいファイルが作成されます。
a+ 読み書きモードでファイルを開きます。ファイルが存在する場合は、ファイルポインタはファイルの末尾に配置されます。ファイルが存在しない場合は、新しいファイルが作成されます。
# ファイルを開く
f = open("example.txt", "w")

# write()は書き込まれた文字数を返します。書き込む内容は文字列である必要があります。
f.write("Pythonは素晴らしい言語です。
はい、本当に素晴らしいです!!
")

# read(size)はファイルからsizeバイトを読み込み、文字列を返します。sizeを省略すると、すべての内容が返されます。
content = f.read()

# readline(size)は指定された長さの行を読み込みます。sizeを省略すると、1行を読み込みます。
line = f.readline()

# ファイルを閉じる
f.close()

# with文を使うと、ファイルのクローズを自動的に処理します
with open('example.txt', 'r') as f:
   read_data = f.read()

pickle(シリアライズとデシリアライズ)

pickleモジュールを使うと、プログラム中のオブジェクト情報をファイルに保存し、永続化できます。

デシリアライズ操作では、ファイルから前回保存したオブジェクトを再構築できます。

import pickle

# データオブジェクトをファイルに保存
data1 = {'a': [1, 2.0, 3, 4+6j],
         'b': ('string', u'Unicode string'),
         'c': None}

selfref_list = [1, 2, 3]
selfref_list.append(selfref_list)

with open('data.pkl', 'wb') as output:
    # 辞書をプロトコル0でpickle化
    pickle.dump(data1, output)
    # リストを最高プロトコルでpickle化
    pickle.dump(selfref_list, output, -1)
import pprint, pickle

# ファイルからPythonオブジェクトを再構築
with open('data.pkl', 'rb') as pkl_file:
    data1 = pickle.load(pkl_file)
    pprint.pprint(data1)

    data2 = pickle.load(pkl_file)
    pprint.pprint(data2)

例外処理

例外処理

try-except文で例外を処理します。

1つのtryブロックに複数のexceptを含めることができますが、一度に1つのexceptしか実行されません。

1つのexceptで複数の例外を処理するには、例外をタプルで囲みます。

最後のexceptで例外名を省略すると、すべての例外をキャッチします。

elseはすべてのexceptの後に配置する必要があります。tryブロックで例外が発生しなかった場合に実行されます。

finallyは、例外が発生したかどうかに関わらず必ず実行されます。もしtryブロックで例外が発生し、かつそれをexceptでキャッチしなかった場合、finallyブロックの実行後に例外が再スローされます。

while True:
    try:
        x = int(input("数字を入力してください: "))
        break
    except ValueError:
        print("数字ではありません。もう一度入力してください。")
    except:
        print("予期しないエラーが発生しました。")
    else:
        print("正常に入力されました。")
    finally:
        print("入力処理を終了します。")

例外の発生

raise文は、例外を明示的に発生させます。通常、exceptブロック内で現在の例外を再スローするために使用されます。

または、raise Exception("メッセージ")のように、新しい例外を発生させることができます。

ユーザー定義例外

独自の例外クラスを作成するには、Exceptionを継承します。

class MyCustomError(Exception):
    def __init__(self, message):
        self.message = message
    def __str__(self):
        return self.message

try:
    raise MyCustomError("エラーが発生しました")
except MyCustomError as e:
    print('カスタム例外が発生しました:', e)

タグ: Python データ型 制御構造 関数 モジュール

7月2日 16:53 投稿