データ型と変数操作 ✨
基本的な変数宣言と型
操作 | コード例 | 説明 |
---|---|---|
整数 (int) |
|
整数値を代入します。 |
浮動小数点数 (float) |
|
小数点を含む数値を代入します。 |
文字列 (str) |
|
シングルクォートまたはダブルクォートで囲みます。トリプルクォートで複数行文字列も可能です。 |
ブール値 (bool) |
|
真 (True) または偽 (False) の値を持ちます。 |
None型 (NoneType) |
|
値が存在しないことを示します。 |
型確認 |
|
type() 関数や isinstance() 関数で変数の型を確認できます。 |
型変換 (キャスト) |
|
str() , int() , float() , bool() などで型を変換します。 |
文字列操作
操作 | コード例 | 説明 |
---|---|---|
連結 |
|
+ 演算子で文字列を連結します。 |
繰り返し |
|
* 演算子で文字列を繰り返します。 |
長さ取得 |
|
len() 関数で文字列の長さを取得します。 |
インデックスアクセス |
|
[] を使って指定位置の文字にアクセスします(0始まり)。負のインデックスは末尾から数えます。 |
スライス |
|
[start:stop:step] で部分文字列を抽出します。 |
検索 (find/index) |
|
find() は見つからない場合に-1を返し、index() はエラー (ValueError) を送出します。rfind() は右から検索します。 |
置換 (replace) |
|
文字列内の部分文字列を別の文字列に置換します。第3引数で置換回数を指定できます。 |
分割 (split) |
|
指定した区切り文字で文字列を分割し、リストを返します。引数を省略すると空白文字(スペース、タブ、改行など)で分割します。 |
結合 (join) |
|
リストなどのイテラブルな要素を、指定した文字列で結合します。 |
大文字/小文字変換 |
|
文字列全体または特定のルールで大文字/小文字を変換します。 |
空白除去 (strip) |
|
文字列の両端、左端、右端から空白文字(スペース、タブ、改行など)を除去します。引数で除去する文字を指定することも可能です。 |
書式設定 (f-string) |
|
Python 3.6以降で推奨される方法。文字列の前に `f` をつけ、 `{}` 内に変数や式を記述します。書式指定も可能です。 |
書式設定 (format) |
|
format() メソッドを使用します。位置引数、キーワード引数、インデックス指定が可能です。 |
制御フロー 🚦
条件分岐 (if, elif, else)
score = 75
if score >= 90:
print("優")
elif score >= 70:
print("良")
elif score >= 50:
print("可")
else:
print("不可")
# 出力: 良
# 1行で書く (三項演算子のような形式)
result = "合格" if score >= 60 else "不合格"
print(result) # 出力: 合格
# 条件式の組み合わせ (and, or, not)
age = 25
is_student = False
if age < 30 and not is_student:
print("若手社会人割引")
elif age >= 65 or is_student:
print("シニア・学生割引")
条件に応じて処理を分岐させます。elif
は複数記述可能で、else
は省略可能です。
ループ (for)
# リストの要素を順に処理
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
# 出力:
# apple
# banana
# cherry
# range() を使った繰り返し
# 0から4まで (5回)
for i in range(5):
print(i, end=" ") # 0 1 2 3 4
print()
# 1から5まで
for i in range(1, 6):
print(i, end=" ") # 1 2 3 4 5
print()
# 0から10まで2つ飛ばし
for i in range(0, 11, 2):
print(i, end=" ") # 0 2 4 6 8 10
print()
# enumerate() でインデックスと要素を同時に取得
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
# 出力:
# 0: apple
# 1: banana
# 2: cherry
# 辞書のキーと値をループ
scores = {"math": 80, "science": 90}
# キーのみ
for key in scores:
print(key) # math, science
# 値のみ
for value in scores.values():
print(value) # 80, 90
# キーと値
for key, value in scores.items():
print(f"{key}: {value}") # math: 80, science: 90
# ループの制御 (break, continue)
for i in range(10):
if i == 5:
break # ループを中断
if i % 2 == 0:
continue # 現在のイテレーションをスキップして次に進む
print(i, end=" ") # 1 3
print()
# for...else 文 (breakされずにループが完了した場合にelseブロックが実行される)
for i in range(3):
print(i)
else:
print("ループ完了")
# 出力:
# 0
# 1
# 2
# ループ完了
for i in range(3):
if i == 1:
break
print(i)
else:
print("ループ完了") # これは実行されない
# 出力:
# 0
イテラブル(リスト、タプル、文字列、rangeオブジェクトなど)の要素を順番に取り出して処理します。
ループ (while)
count = 0
while count < 5:
print(count, end=" ") # 0 1 2 3 4
count += 1
print()
# break と else を使った例
n = 10
while n > 0:
n -= 1
if n == 5:
print("中断!")
break
print(n, end=" ") # 9 8 7 6
else:
print("ループ完了") # breakされたので実行されない
print()
# 無限ループ (意図的に作る場合)
# while True:
# user_input = input("何か入力してください (exitで終了): ")
# if user_input == "exit":
# break
# print(f"入力: {user_input}")
指定した条件が真 (True) の間、処理を繰り返します。
関数 🔧
基本的な関数の定義と呼び出し
# 引数なし、戻り値なし
def greet():
print("こんにちは!")
greet() # 出力: こんにちは!
# 引数あり、戻り値あり
def add(a, b):
"""二つの数を足して返す関数""" # Docstring (関数の説明)
return a + b
result = add(5, 3)
print(result) # 出力: 8
print(add.__doc__) # Docstringの表示
# デフォルト引数値
def say_hello(name="ゲスト"):
print(f"ようこそ、{name}さん!")
say_hello("太郎") # 出力: ようこそ、太郎さん!
say_hello() # 出力: ようこそ、ゲストさん!
# キーワード引数 (引数の順序を問わない)
def describe_pet(animal_type, pet_name):
print(f"私は {animal_type} を飼っています。")
print(f"名前は {pet_name} です。")
describe_pet(animal_type="ハムスター", pet_name="もこ")
describe_pet(pet_name="ポチ", animal_type="犬") # 順序を変えてもOK
可変長引数
# *args (複数の位置引数をタプルとして受け取る)
def sum_all(*numbers):
total = 0
for num in numbers:
total += num
return total
print(sum_all(1, 2, 3)) # 出力: 6
print(sum_all(10, 20, 30, 40)) # 出力: 100
# **kwargs (複数のキーワード引数を辞書として受け取る)
def print_info(**info):
for key, value in info.items():
print(f"{key}: {value}")
print_info(name="花子", age=28, city="東京")
# 出力:
# name: 花子
# age: 28
# city: 東京
# *args と **kwargs の両方を使う (順番に注意)
def process_data(id, *scores, **metadata):
print(f"ID: {id}")
print(f"Scores: {scores}") # タプル
print(f"Metadata: {metadata}") # 辞書
process_data(101, 85, 92, 78, subject="Math", date="2025-04-03")
# 出力:
# ID: 101
# Scores: (85, 92, 78)
# Metadata: {'subject': 'Math', 'date': '2025-04-03'}
スコープ (ローカル変数とグローバル変数)
global_var = "私はグローバル"
def my_function():
local_var = "私はローカル"
print(local_var)
print(global_var) # グローバル変数は参照可能
my_function()
# 出力:
# 私はローカル
# 私はグローバル
# print(local_var) # NameError: name 'local_var' is not defined (関数外からはアクセス不可)
def modify_global():
global global_var # グローバル変数を変更することを宣言
global_var = "グローバル変数を変更しました"
modify_global()
print(global_var) # 出力: グローバル変数を変更しました
関数内で定義された変数はローカル変数、関数の外で定義された変数はグローバル変数です。関数内でグローバル変数の値を変更するには global
キーワードが必要です。
ラムダ式 (無名関数)
# 通常の関数
def double(x):
return x * 2
# ラムダ式
double_lambda = lambda x: x * 2
print(double(5)) # 出力: 10
print(double_lambda(5)) # 出力: 10
# 引数を複数取るラムダ式
add_lambda = lambda x, y: x + y
print(add_lambda(3, 4)) # 出力: 7
# map() や filter() と組み合わせて使う
numbers = [1, 2, 3, 4, 5]
# 各要素を2倍にする
doubled_numbers = list(map(lambda x: x * 2, numbers))
print(doubled_numbers) # [2, 4, 6, 8, 10]
# 偶数のみを抽出する
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # [2, 4]
# リストのソートキーとして使う
points = [(1, 2), (3, 1), (5, 4), (2, 3)]
# y座標でソート
points.sort(key=lambda p: p[1])
print(points) # [(3, 1), (1, 2), (2, 3), (5, 4)]
lambda 引数: 式
の形式で、簡単な処理を行う一行の関数を定義できます。
モジュールとパッケージ 📦
モジュールのインポート
方法 | コード例 | 説明 |
---|---|---|
モジュール全体をインポート |
|
import モジュール名 でインポートし、モジュール名.要素名 でアクセスします。 |
別名を付けてインポート |
|
import モジュール名 as 別名 でインポートし、別名.要素名 でアクセスします。慣例的に使われる別名があります (例: numpy -> np, pandas -> pd)。 |
特定の要素のみインポート |
|
from モジュール名 import 要素名1, 要素名2 でインポートし、要素名を直接使用できます。名前の衝突に注意が必要です。 |
全ての要素をインポート (非推奨) |
|
from モジュール名 import * ですべての要素をインポートしますが、どの要素がどのモジュールから来たのか分かりにくくなるため、通常は避けるべきです。 |
パッケージ
複数のモジュールをまとめたものがパッケージ(ディレクトリ)です。パッケージ内のモジュールをインポートするにはドット (.
) を使います。
# 例: mypackage というディレクトリがあり、その中に module1.py がある場合
# import mypackage.module1
# mypackage.module1.my_function()
# from mypackage import module1
# module1.my_function()
# from mypackage.module1 import my_function
# my_function()
# パッケージ初期化ファイル (__init__.py)
# パッケージディレクトリ内にある __init__.py は、そのディレクトリがパッケージであることを示します。
# インポート時に初期化処理を行ったり、パッケージの属性を定義したりできます。
標準ライブラリの例
math
: 数学関数 (三角関数、対数、平方根など)random
: 乱数生成datetime
: 日付と時刻の操作os
: オペレーティングシステムとのインタフェース (ファイル操作、プロセス管理など)sys
: Pythonインタプリタに関する情報や機能json
: JSONデータのエンコードとデコードre
: 正規表現操作collections
: 高度なデータ構造 (defaultdict, Counter, dequeなど)
Pythonには豊富な標準ライブラリが用意されており、別途インストールせずに利用できます。
外部ライブラリのインストール (pip)
pip
はPythonのパッケージ管理システムです。コマンドラインで使用します。
# ライブラリのインストール
pip install requests numpy pandas
# 特定のバージョンをインストール
pip install requests==2.25.1
# ライブラリのアンインストール
pip uninstall requests
# インストール済みライブラリの一覧表示
pip list
# ライブラリの情報を表示
pip show requests
# requirements.txt を使った一括インストール/エクスポート
# 現在の環境のライブラリをファイルに出力
pip freeze > requirements.txt
# ファイルからライブラリを一括インストール
pip install -r requirements.txt
ファイル操作 📁
ファイルのオープンとクローズ
# 基本的な書き込み (w: 上書き)
# 'with' を使うと自動的にファイルがクローズされるため推奨される
try:
with open("my_file.txt", "w", encoding="utf-8") as f:
f.write("ファイルに書き込む最初の行。\n")
f.write("2行目です。\n")
print("ファイル書き込み完了 (my_file.txt)")
except IOError as e:
print(f"ファイル書き込みエラー: {e}")
# 基本的な読み込み (r: 読み込み)
try:
with open("my_file.txt", "r", encoding="utf-8") as f:
content = f.read() # ファイル全体を文字列として読み込む
print("--- ファイル内容 (read) ---")
print(content)
with open("my_file.txt", "r", encoding="utf-8") as f:
print("--- ファイル内容 (readline) ---")
line1 = f.readline() # 1行ずつ読み込む
print(f"1行目: {line1.strip()}") # strip()で改行文字を除去
line2 = f.readline()
print(f"2行目: {line2.strip()}")
with open("my_file.txt", "r", encoding="utf-8") as f:
print("--- ファイル内容 (readlines) ---")
lines = f.readlines() # 全行をリストとして読み込む
print(lines)
for line in lines:
print(f"リストの要素: {line.strip()}")
# イテレータを使った効率的な行単位読み込み
with open("my_file.txt", "r", encoding="utf-8") as f:
print("--- ファイル内容 (for文) ---")
for line in f: # ファイルオブジェクトはイテレータとしても使える
print(f"行: {line.strip()}")
except FileNotFoundError:
print("エラー: my_file.txt が見つかりません。")
except IOError as e:
print(f"ファイル読み込みエラー: {e}")
# 追記モード (a: append)
try:
with open("my_file.txt", "a", encoding="utf-8") as f:
f.write("これは追記された行です。\n")
print("ファイル追記完了 (my_file.txt)")
with open("my_file.txt", "r", encoding="utf-8") as f:
print("--- ファイル内容 (追記後) ---")
print(f.read())
except IOError as e:
print(f"ファイル追記エラー: {e}")
# バイナリモード (wb: 書き込み, rb: 読み込み)
# 画像ファイルなどを扱う場合
# try:
# with open("image.jpg", "rb") as f_in:
# img_data = f_in.read()
# with open("image_copy.jpg", "wb") as f_out:
# f_out.write(img_data)
# print("バイナリファイルのコピー完了")
# except FileNotFoundError:
# print("エラー: image.jpg が見つかりません。")
# except IOError as e:
# print(f"バイナリファイル操作エラー: {e}")
'r'
: 読み込み (デフォルト)'w'
: 書き込み (ファイルが存在すれば上書き)'a'
: 追記 (ファイルの末尾に追加)'x'
: 新規作成書き込み (ファイルが存在するとエラー)'b'
: バイナリモード (例:'rb'
,'wb'
)'t'
: テキストモード (デフォルト)'+'
: 読み書き両用 (例:'r+'
,'w+'
,'a+'
)
encoding="utf-8"
を指定することで、多くの環境で文字化けを防ぐことができます。
ファイル/ディレクトリ操作 (osモジュール)
import os
import shutil # 高レベルなファイル操作 (コピー、移動など)
# カレントディレクトリの取得
current_dir = os.getcwd()
print(f"カレントディレクトリ: {current_dir}")
# ファイルやディレクトリの存在確認
file_exists = os.path.exists("my_file.txt")
dir_exists = os.path.exists("my_directory")
print(f"my_file.txt は存在するか: {file_exists}")
print(f"my_directory は存在するか: {dir_exists}")
# ファイルかディレクトリかの判別
is_file = os.path.isfile("my_file.txt")
is_dir = os.path.isdir("my_file.txt") # これは False になるはず
print(f"my_file.txt はファイルか: {is_file}")
print(f"my_file.txt はディレクトリか: {is_dir}")
# ディレクトリの作成
if not os.path.exists("my_directory"):
os.mkdir("my_directory") # 1階層のみ作成
print("my_directory を作成しました。")
if not os.path.exists("nested/dir"):
os.makedirs("nested/dir") # 複数階層をまとめて作成
print("nested/dir を作成しました。")
# ファイル名の変更 / 移動
if os.path.exists("my_file.txt"):
os.rename("my_file.txt", "renamed_file.txt")
print("my_file.txt を renamed_file.txt にリネームしました。")
# shutil を使った移動
if os.path.exists("renamed_file.txt"):
shutil.move("renamed_file.txt", "my_directory/moved_file.txt")
print("renamed_file.txt を my_directory/moved_file.txt に移動しました。")
# ファイルのコピー
if os.path.exists("my_directory/moved_file.txt"):
shutil.copy("my_directory/moved_file.txt", "copied_file.txt")
print("moved_file.txt を copied_file.txt にコピーしました。")
# ディレクトリ内のファイル/ディレクトリ一覧取得
if os.path.exists("my_directory"):
print(f"my_directory の中身: {os.listdir('my_directory')}")
# ファイルの削除
if os.path.exists("copied_file.txt"):
os.remove("copied_file.txt")
print("copied_file.txt を削除しました。")
# ディレクトリの削除 (空である必要あり)
if os.path.exists("my_directory/moved_file.txt"): # 中身を先に消す
os.remove("my_directory/moved_file.txt")
if os.path.exists("my_directory"):
os.rmdir("my_directory")
print("my_directory を削除しました。")
# ディレクトリの削除 (中身ごと)
if os.path.exists("nested"):
shutil.rmtree("nested")
print("nested ディレクトリを中身ごと削除しました。")
# パスの結合 (OSに合わせた区切り文字を使用)
file_path = os.path.join("dir1", "dir2", "file.txt")
print(f"結合されたパス: {file_path}") # Windowsなら "dir1\\dir2\\file.txt", Linux/macOSなら "dir1/dir2/file.txt"
# パスからファイル名やディレクトリ名を取得
basename = os.path.basename(file_path) # "file.txt"
dirname = os.path.dirname(file_path) # "dir1/dir2" または "dir1\\dir2"
print(f"ファイル名: {basename}, ディレクトリ名: {dirname}")
エラーハンドリング (try, except, finally) ❌
基本的な例外処理
try:
# エラーが発生する可能性のある処理
x = 10 / 0
print("この行は実行されません")
except ZeroDivisionError:
# ZeroDivisionError が発生した場合の処理
print("エラー: 0で割ることはできません。")
except TypeError as e:
# TypeError が発生した場合の処理 (エラーオブジェクト e を利用可能)
print(f"型エラーが発生しました: {e}")
except Exception as e:
# 上記以外の何らかの例外が発生した場合の処理
print(f"予期せぬエラーが発生しました: {e}")
else:
# try ブロックで例外が発生しなかった場合の処理 (オプション)
print("エラーは発生しませんでした。")
finally:
# 例外の有無にかかわらず、必ず実行される処理 (オプション)
print("処理を終了します。")
# 例: ファイル操作と組み合わせる
try:
f = open("non_existent_file.txt", "r")
content = f.read()
print(content)
except FileNotFoundError:
print("エラー: ファイルが見つかりません。")
finally:
# ファイルが開かれていればクローズする(より安全なのは with 文)
if 'f' in locals() and not f.closed:
f.close()
print("ファイルをクローズしました (finally)")
try
ブロック内でエラーが発生すると、対応する except
ブロックが実行されます。finally
ブロックは常に実行され、リソースの解放などに使われます。
独自例外の発生 (raise)
def check_age(age):
if age < 0:
raise ValueError("年齢に負の値は指定できません。")
elif age < 18:
print("未成年です。")
else:
print("成人です。")
try:
check_age(25) # 成人です。
check_age(10) # 未成年です。
check_age(-5) # ここで ValueError が発生
except ValueError as e:
print(f"エラーをキャッチ: {e}")
# 独自例外クラスの定義
class MyCustomError(Exception):
"""独自の例外クラス"""
pass
def custom_process(value):
if value == "error":
raise MyCustomError("カスタムエラーが発生しました!")
else:
print(f"処理成功: {value}")
try:
custom_process("ok")
custom_process("error")
except MyCustomError as e:
print(f"カスタムエラーをキャッチ: {e}")
raise
キーワードを使って意図的に例外を発生させることができます。独自の例外クラスを定義することも可能です。
データ構造 📚
リスト (List) – 順序あり, 変更可能
操作 | コード例 | 説明 |
---|---|---|
作成 |
|
[] で作成。異なるデータ型を混在可能。 |
要素アクセス |
|
インデックス (0始まり) やスライスでアクセス。 |
要素変更 |
|
インデックスを指定して代入。 |
要素追加 (末尾) |
|
append() メソッドを使用。 |
要素挿入 |
|
insert(index, element) メソッドを使用。 |
リスト結合 |
|
+ 演算子または extend() メソッドを使用。 |
要素削除 (値指定) |
|
remove() メソッドを使用。要素が存在しないと ValueError。 |
要素削除 (インデックス指定) |
|
pop(index) は要素を削除して返し、インデックス省略時は末尾を削除。del 文でも削除可能。 |
要素検索 |
|
in 演算子で存在確認。index() でインデックスを取得 (存在しないと ValueError)。 |
要素数カウント |
|
count() メソッドを使用。 |
ソート |
|
sort() は元のリストを変更、sorted() は新しいソート済みリストを返します。 |
逆順 |
|
reverse() メソッドを使用。 |
リスト内包表記 |
|
簡潔な構文でリストを生成。条件分岐 (if) も含めることができます。 |
タプル (Tuple) – 順序あり, 変更不可能
操作 | コード例 | 説明 |
---|---|---|
作成 |
|
() で作成。要素が1つの場合は末尾にカンマが必要。 |
要素アクセス |
|
リストと同様にインデックスやスライスでアクセス。 |
要素変更/追加/削除 |
|
タプルはイミュータブル(変更不可能)なため、要素の変更、追加、削除はできません。 |
要素検索 |
|
in , index() , count() はリストと同様に使用可能。 |
タプル結合 |
|
+ 演算子で新しいタプルを作成できます。 |
アンパッキング |
|
タプルの要素を個別の変数に代入できます。 |
タプルは変更されない値をまとめるのに適しています (例: 関数の戻り値、辞書のキー)。リストよりもメモリ効率が若干良い場合があります。
辞書 (Dictionary) – キーと値のペア, 順序あり (Python 3.7+), 変更可能
操作 | コード例 | 説明 |
---|---|---|
作成 |
|
{} で作成。キー: 値 のペアで構成。キーはイミュータブルな型 (文字列、数値、タプルなど) である必要があります。 |
値アクセス |
|
[] でアクセス (キーが存在しないと KeyError)。get() メソッドを使うと安全にアクセスできます。 |
値の変更/追加 |
|
[] を使って代入。update() で複数のキー/値を一度に追加・更新できます。 |
要素削除 |
|
pop(key) は指定したキーの要素を削除して値を返します。popitem() は最後の要素を削除して(キー, 値)のタプルを返します。del 文でも削除可能。 |
キー/値/アイテムの取得 |
|
keys() , values() , items() メソッドで、それぞれキー、値、(キー, 値)タプルのビューオブジェクトを取得します。forループで直接使用できます。 |
キーの存在確認 |
|
in 演算子でキーが存在するかどうかを確認します。 |
要素数 |
|
len() 関数でキーと値のペアの数を取得します。 |
Python 3.7以降、辞書は挿入された順序を保持します。
セット (Set) – 順序なし, 重複なし, 変更可能
操作 | コード例 | 説明 |
---|---|---|
作成 |
|
{} で作成(ただし空のセットは set() )。重複する要素は含まれません。順序は保証されません。 |
要素追加 |
|
add() メソッドを使用。 |
複数要素追加 |
|
update() メソッドでイテラブル(リスト、タプル、他のセットなど)から複数の要素を追加。 |
要素削除 |
|
remove() は要素が存在しないと KeyError。discard() はエラーにならない。pop() は任意の要素を削除して返します。clear() ですべての要素を削除。 |
要素の存在確認 |
|
in 演算子を使用(高速です)。 |
集合演算 (和集合) |
|
union() メソッドまたは | 演算子。 |
集合演算 (積集合) |
|
intersection() メソッドまたは & 演算子。 |
集合演算 (差集合) |
|
difference() メソッドまたは - 演算子。 |
集合演算 (対称差集合) |
|
symmetric_difference() メソッドまたは ^ 演算子。 |
部分集合/上位集合 |
|
issubset() (<= ), issuperset() (>= ), isdisjoint() メソッドや比較演算子で判定。 |
セットは要素の存在確認や重複削除を高速に行いたい場合に便利です。
フローズンセット (frozenset) – 順序なし, 重複なし, 変更不可能
fs = frozenset([1, 2, 3, 2]) # frozenset({1, 2, 3})
# fs.add(4) # AttributeError: 'frozenset' object has no attribute 'add'
# fs.remove(1) # AttributeError
# 変更不可なので、辞書のキーや他のセットの要素になれる
my_dict = {fs: "これはフローズンセットのキー"}
print(my_dict)
set_of_sets = {{1, 2}, {3, 4}} # TypeError: unhashable type: 'set' (通常のセットはキーや要素になれない)
set_of_frozensets = {frozenset({1, 2}), frozenset({3, 4})} # OK
print(set_of_frozensets)
セットと似ていますが、イミュータブル(変更不可能)です。そのため、辞書のキーやセットの要素として使用できます。
オブジェクト指向プログラミング (クラス) 🧱
基本的なクラス定義とインスタンス化
class Dog:
# クラス変数 (全てのインスタンスで共有)
species = "Canis familiaris"
# 初期化メソッド (コンストラクタ)
def __init__(self, name, age):
# インスタンス変数 (各インスタンス固有)
self.name = name
self.age = age
print(f"{self.name} が生成されました!")
# インスタンスメソッド
def bark(self):
print(f"{self.name}: ワン!")
def describe(self):
return f"{self.name} は {self.age} 歳です。"
# クラスメソッド (クラス自体にアクセス、第一引数は cls)
@classmethod
def get_species(cls):
return cls.species
# スタティックメソッド (クラスやインスタンスの状態に依存しない)
@staticmethod
def is_adult(age):
return age >= 1
# インスタンスの生成
my_dog = Dog("ポチ", 3)
another_dog = Dog("ハチ", 5)
# メソッドの呼び出し
my_dog.bark() # ポチ: ワン!
print(my_dog.describe()) # ポチ は 3 歳です。
another_dog.bark() # ハチ: ワン!
# インスタンス変数へのアクセス
print(my_dog.name) # ポチ
print(another_dog.age) # 5
# クラス変数へのアクセス
print(Dog.species) # Canis familiaris
print(my_dog.species) # インスタンス経由でもアクセス可能
# クラスメソッドの呼び出し
print(Dog.get_species()) # Canis familiaris
# スタティックメソッドの呼び出し
print(Dog.is_adult(my_dog.age)) # True
print(Dog.is_adult(0.5)) # False
継承
# 親クラス (スーパークラス)
class Animal:
def __init__(self, name):
self.name = name
print(f"動物 {self.name} が誕生")
def eat(self):
print(f"{self.name} が食事をしています。")
# 子クラス (サブクラス) - Animalクラスを継承
class Cat(Animal):
def __init__(self, name, breed):
# 親クラスの __init__ を呼び出す
super().__init__(name)
self.breed = breed
print(f"{self.breed} の {self.name} が誕生")
# メソッドのオーバーライド (親クラスのメソッドを上書き)
def eat(self):
print(f"{self.name} がキャットフードを食べています。")
# 子クラス独自のメソッド
def meow(self):
print(f"{self.name}: ニャー!")
# 子クラス (サブクラス) - Animalクラスを継承
class Bird(Animal):
def fly(self):
print(f"{self.name} が飛んでいます。")
# インスタンス生成
my_cat = Cat("ミケ", "三毛猫")
my_bird = Bird("ピピ")
# 親クラスから継承したメソッド
my_cat.eat() # ミケ がキャットフードを食べています。 (オーバーライドされたメソッド)
my_bird.eat() # ピピ が食事をしています。 (親クラスのメソッド)
# 子クラス独自のメソッド
my_cat.meow() # ミケ: ニャー!
my_bird.fly() # ピピ が飛んでいます。
# isinstance() で型チェック (継承関係も考慮される)
print(isinstance(my_cat, Cat)) # True
print(isinstance(my_cat, Animal)) # True (親クラスの型でもある)
print(isinstance(my_bird, Cat)) # False
class 子クラス名(親クラス名):
のように記述してクラスを継承します。子クラスは親クラスの属性やメソッドを引き継ぎます。super()
を使うと親クラスのメソッドを呼び出せます。メソッドを子クラスで再定義することをオーバーライドと言います。
特殊メソッド (マジックメソッド)
__init__
のように、アンダースコア (_
) で囲まれたメソッドは特殊メソッドと呼ばれ、特定の操作(インスタンス化、文字列表現、演算子の動作など)に関連して自動的に呼び出されます。
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
# print() や str() で呼び出される (ユーザー向けの文字列表現)
def __str__(self):
return f"Vector({self.x}, {self.y})"
# repr() やインタラクティブシェルで呼び出される (開発者向けの正確な表現)
def __repr__(self):
return f"Vector(x={self.x}, y={self.y})"
# len() で呼び出される
def __len__(self):
# 例として、原点からの距離 (大きさ) を返す (本来は整数を返すべきだが例として)
import math
return int(math.sqrt(self.x**2 + self.y**2))
# + 演算子で呼び出される
def __add__(self, other):
if isinstance(other, Vector):
return Vector(self.x + other.x, self.y + other.y)
else:
# 未対応の型との加算は NotImplemented を返すのが慣例
return NotImplemented
# == 演算子で呼び出される
def __eq__(self, other):
if isinstance(other, Vector):
return self.x == other.x and self.y == other.y
return False
v1 = Vector(2, 3)
v2 = Vector(4, 5)
v3 = Vector(2, 3)
print(v1) # 出力: Vector(2, 3) ( __str__ が呼ばれる)
print(repr(v1)) # 出力: Vector(x=2, y=3) ( __repr__ が呼ばれる)
print(len(v1)) # 出力: 3 (原点からの距離の整数部、__len__ が呼ばれる)
v_sum = v1 + v2
print(v_sum) # 出力: Vector(6, 8) ( __add__ が呼ばれる)
print(v1 == v2) # 出力: False ( __eq__ が呼ばれる)
print(v1 == v3) # 出力: True ( __eq__ が呼ばれる)
# print(v1 + 10) # エラーになる (NotImplemented が返るため)
他にも __getitem__
(インデックスアクセス), __setitem__
(インデックス代入), __delitem__
(インデックス削除), 比較演算子 (__lt__
, __le__
, __gt__
, __ge__
, __ne__
) など、多数の特殊メソッドがあります。
正規表現 🔍
re
モジュールを使って、文字列の中から特定のパターンを検索、置換、抽出します。
基本的な使い方
import re
text = "私の電話番号は 080-1234-5678 で、郵便番号は 123-4567 です。"
pattern_phone = r"\d{3}-\d{4}-\d{4}" # 電話番号のパターン (r"" は raw 文字列)
pattern_zip = r"\d{3}-\d{4}" # 郵便番号のパターン (電話番号と一部重複)
# search(): パターンに最初にマッチした箇所を探す
match_phone = re.search(pattern_phone, text)
if match_phone:
print(f"電話番号が見つかりました: {match_phone.group(0)}") # マッチした文字列全体
print(f"開始位置: {match_phone.start()}, 終了位置: {match_phone.end()}")
else:
print("電話番号は見つかりませんでした。")
# match(): 文字列の *先頭* からパターンにマッチするか試す
match_zip_at_start = re.match(pattern_zip, text) # 先頭ではないのでマッチしない
if match_zip_at_start:
print("文字列の先頭が郵便番号パターンにマッチしました。")
else:
print("文字列の先頭は郵便番号パターンにマッチしませんでした。")
# findall(): パターンにマッチする全ての箇所をリストで返す
all_matches = re.findall(pattern_zip, text) # 電話番号の一部もマッチする
print(f"郵便番号パターンにマッチする箇所: {all_matches}") # ['080-1234', '123-4567']
# finditer(): パターンにマッチする全ての箇所をイテレータ (Matchオブジェクト) で返す
print("郵便番号パターンにマッチする箇所の詳細:")
for m in re.finditer(pattern_zip, text):
print(f" Match: {m.group(0)}, Start: {m.start()}, End: {m.end()}")
# sub(): パターンにマッチした箇所を置換する
replaced_text = re.sub(pattern_phone, "[電話番号]", text)
print(f"置換後: {replaced_text}") # 私の電話番号は [電話番号] で、郵便番号は 123-4567 です。
# split(): パターンにマッチした箇所で文字列を分割する
text_csv = "apple,banana;orange grape"
# カンマまたはセミコロンまたはスペースで分割
parts = re.split(r"[,;\s]+", text_csv) # + は1回以上の繰り返し
print(f"分割結果: {parts}") # ['apple', 'banana', 'orange', 'grape']
# compile(): パターンを事前にコンパイルして効率化 (繰り返し使う場合)
compiled_pattern = re.compile(r"\d+") # 1桁以上の数字
text_numbers = "数字は 1, 10, 100 です。"
numbers_found = compiled_pattern.findall(text_numbers)
print(f"コンパイル済みパターンでの検索結果: {numbers_found}") # ['1', '10', '100']
メタ文字と特殊シーケンス
記号 | 意味 | 例 |
---|---|---|
. | 任意の一文字(改行を除く) | a.c -> “abc”, “a c”, “a!c” |
^ | 文字列の先頭 | ^abc -> “abc…” |
$ | 文字列の末尾 | xyz$ -> “…xyz” |
* | 直前の文字の0回以上の繰り返し | ab*c -> “ac”, “abc”, “abbc” |
+ | 直前の文字の1回以上の繰り返し | ab+c -> “abc”, “abbc” (ac はマッチしない) |
? | 直前の文字の0回または1回の繰り返し | ab?c -> “ac”, “abc” |
{n} | 直前の文字のn回の繰り返し | a{3} -> “aaa” |
{n,} | 直前の文字のn回以上の繰り返し | a{2,} -> “aa”, “aaa”, … |
{n,m} | 直前の文字のn回以上m回以下の繰り返し | a{2,4} -> “aa”, “aaa”, “aaaa” |
[] | 文字クラス(いずれかの一文字) | [abc] -> “a” or “b” or “c” |
[^] | 否定文字クラス([]内の文字以外) | [^abc] -> “a”, “b”, “c” 以外の文字 |
[a-z] | 範囲指定 | [a-zA-Z0-9] -> 英数字 |
| | または (OR) | cat|dog -> “cat” or “dog” |
() | グループ化 | (ab)+ -> “ab”, “abab”, … |
\d | 任意の数字 ([0-9] と同じ) | \d{3} -> “123” |
\D | 数字以外の文字 ([^0-9] と同じ) | |
\w | 英数字またはアンダースコア ([a-zA-Z0-9_] と同じ) | |
\W | 英数字・アンダースコア以外の文字 ([^a-zA-Z0-9_] と同じ) | |
\s | 空白文字 (スペース, タブ, 改行など) | |
\S | 空白文字以外の文字 | |
\b | 単語境界 (単語の開始または終了位置) | \bword\b -> “word” ( “keyword” の word にはマッチしない) |
\B | 単語境界以外 | |
\\ | バックスラッシュ自体 | |
\ meta | メタ文字のエスケープ | \. -> “.” (ドット文字自体) |
キャプチャグループ
パターンの一部を ()
で囲むと、その部分にマッチした文字列を後で取り出すことができます。
text = "Name: Alice, Age: 30"
# グループ1: 名前 (\w+), グループ2: 年齢 (\d+)
pattern = r"Name: (\w+), Age: (\d+)"
match = re.search(pattern, text)
if match:
print(f"マッチ全体: {match.group(0)}") # Name: Alice, Age: 30
print(f"グループ1 (名前): {match.group(1)}") # Alice
print(f"グループ2 (年齢): {match.group(2)}") # 30
print(f"全グループのタプル: {match.groups()}") # ('Alice', '30')
# 名前付きキャプチャグループ (?P...)
pattern_named = r"Name: (?P\w+), Age: (?P\d+)"
match_named = re.search(pattern_named, text)
if match_named:
print(f"名前 (名前付き): {match_named.group('name')}") # Alice
print(f"年齢 (名前付き): {match_named.group('age')}") # 30
print(f"名前付きグループの辞書: {match_named.groupdict()}") # {'name': 'Alice', 'age': '30'}
# findall でグループを使うと、グループ部分のみがタプルで返される
text_pairs = "ID: A1, Value: 100; ID: B2, Value: 200"
pattern_pairs = r"ID: (\w+), Value: (\d+)"
pairs = re.findall(pattern_pairs, text_pairs)
print(f"findall とグループ: {pairs}") # [('A1', '100'), ('B2', '200')]
フラグ
検索の挙動を変更するフラグを指定できます。
text = "Python is FUN.\nCase insensitive search."
# re.IGNORECASE / re.I : 大文字小文字を無視
match_icase = re.search(r"python", text, re.IGNORECASE)
if match_icase:
print(f"大文字小文字無視: {match_icase.group(0)}") # Python
# re.MULTILINE / re.M : ^ と $ が各行の先頭/末尾にもマッチする
match_mline = re.search(r"^Case", text, re.MULTILINE)
if match_mline:
print(f"複数行モード (^): {match_mline.group(0)}") # Case
# re.DOTALL / re.S : . (ドット) が改行文字にもマッチする
match_dotall = re.search(r"FUN.*search", text, re.DOTALL)
if match_dotall:
print(f"DOTALL モード: マッチあり") # マッチあり (改行を含むため)
else:
print(f"DOTALL モード: マッチなし")
match_normal = re.search(r"FUN.*search", text)
if match_normal:
print(f"通常モード: マッチあり")
else:
print(f"通常モード: マッチなし") # マッチなし (. が改行にマッチしないため)
# 複数のフラグは | で組み合わせる
match_combined = re.search(r"^python.*search.$", text, re.I | re.M | re.S)
if match_combined:
print("複数フラグ: マッチあり")
日付と時刻 ⏰
datetime
モジュールを使って日付や時刻を扱います。
現在の日付と時刻
from datetime import datetime, date, time, timedelta
# 現在の日付と時刻
now = datetime.now()
print(f"現在の日時: {now}")
# UTC (協定世界時) の現在時刻
utcnow = datetime.utcnow()
print(f"現在のUTC日時: {utcnow}")
# 今日の日付
today = date.today()
print(f"今日の日付: {today}")
# 個別の要素へのアクセス
print(f"年: {now.year}, 月: {now.month}, 日: {now.day}")
print(f"時: {now.hour}, 分: {now.minute}, 秒: {now.second}, マイクロ秒: {now.microsecond}")
print(f"曜日: {now.weekday()} (月曜=0, 日曜=6)") # 曜日 (0-6)
print(f"ISO曜日: {now.isoweekday()} (月曜=1, 日曜=7)") # ISO 8601 曜日 (1-7)
特定の日付や時刻の作成
# 特定の日付を作成
d = date(2025, 5, 15)
print(f"指定した日付: {d}")
# 特定の時刻を作成
t = time(10, 30, 55)
print(f"指定した時刻: {t}")
# 特定の日時を作成
dt = datetime(2025, 12, 24, 18, 0, 0)
print(f"指定した日時: {dt}")
文字列との変換 (strftime, strptime)
now = datetime.now()
# datetime オブジェクト -> 文字列 (strftime: format)
formatted_string = now.strftime("%Y年%m月%d日 %H時%M分%S秒 (%A)")
print(f"フォーマットされた文字列: {formatted_string}")
# 一般的なフォーマット: YYYY-MM-DD HH:MM:SS
iso_format = now.strftime("%Y-%m-%d %H:%M:%S")
print(f"ISO風フォーマット: {iso_format}")
# ISO 8601 形式 (T区切り)
iso_8601 = now.isoformat()
print(f"ISO 8601形式: {iso_8601}")
# 文字列 -> datetime オブジェクト (strptime: parse)
date_string = "2024-07-20 15:30:00"
format_code = "%Y-%m-%d %H:%M:%S"
parsed_datetime = datetime.strptime(date_string, format_code)
print(f"パースされた日時: {parsed_datetime}")
print(f"パースされた日時の型: {type(parsed_datetime)}")
# 無効なフォーマットや文字列だと ValueError
try:
datetime.strptime("2024/07/20", format_code)
except ValueError as e:
print(f"パースエラー: {e}")
%Y
: 4桁の年 (例: 2025)%y
: 2桁の年 (例: 25)%m
: 2桁の月 (01-12)%d
: 2桁の日 (01-31)%H
: 24時間表記の時 (00-23)%I
: 12時間表記の時 (01-12)%p
: AM/PM%M
: 2桁の分 (00-59)%S
: 2桁の秒 (00-59)%f
: マイクロ秒 (6桁)%A
: 曜日のフルネーム (例: Thursday)%a
: 曜日の省略形 (例: Thu)%B
: 月のフルネーム (例: April)%b
: 月の省略形 (例: Apr)%Z
: タイムゾーン名%z
: UTCからのオフセット (+HHMM または -HHMM)
日付と時刻の計算 (timedelta)
now = datetime.now()
# 時間差 (timedelta) の作成
delta_1day = timedelta(days=1)
delta_2weeks = timedelta(weeks=2)
delta_3hours = timedelta(hours=3, minutes=30)
print(f"1日後: {now + delta_1day}")
print(f"2週間前: {now - delta_2weeks}")
print(f"3時間30分後: {now + delta_3hours}")
# 二つの日時の差
dt1 = datetime(2025, 4, 1, 10, 0, 0)
dt2 = datetime(2025, 4, 10, 15, 30, 0)
time_difference = dt2 - dt1
print(f"dt1 と dt2 の差: {time_difference}")
print(f"差 (日数): {time_difference.days}")
print(f"差 (秒数): {time_difference.total_seconds()}")
# timedelta の比較
print(f"1日は2週間より短いか: {delta_1day < delta_2weeks}") # True
timedelta
オブジェクトは、時間の間隔を表します。日付や時刻に加算・減算したり、日時間の差を計算したりするのに使います。
Web関連 (requestsライブラリ) 🌐
requests
は、HTTPリクエストを簡単に行うための非常に人気のある外部ライブラリです。 (pip install requests
でインストールが必要です)
基本的なGETリクエスト
import requests
import json # JSONレスポンスを扱うため
url = "https://httpbin.org/get" # テスト用のエンドポイント
try:
# GETリクエストを送信
response = requests.get(url)
# ステータスコードを確認 (200 なら成功)
response.raise_for_status() # エラーがあれば HTTPError を発生させる
print(f"ステータスコード: {response.status_code}")
# レスポンスヘッダー
# print("レスポンスヘッダー:")
# for key, value in response.headers.items():
# print(f" {key}: {value}")
# レスポンスボディ (テキストとして取得)
# print("\nレスポンステキスト:")
# print(response.text)
# レスポンスボディ (JSONとして取得)
try:
json_data = response.json()
print("\nレスポンスJSON:")
# print(json.dumps(json_data, indent=2, ensure_ascii=False)) # 見やすく整形して表示
print(f" Origin IP: {json_data.get('origin')}")
print(f" User-Agent: {json_data.get('headers', {}).get('User-Agent')}")
except json.JSONDecodeError:
print("レスポンスはJSON形式ではありませんでした。")
except requests.exceptions.RequestException as e:
print(f"リクエスト中にエラーが発生しました: {e}")
GETリクエスト (パラメータ付き)
url = "https://httpbin.org/get"
params = {
"query": "Python requests",
"page": 1,
"lang": "ja"
}
try:
response = requests.get(url, params=params)
response.raise_for_status()
print(f"リクエストURL: {response.url}") # 送信された実際のURLを確認できる
json_data = response.json()
print("\nレスポンスJSON (パラメータ付き):")
# print(json.dumps(json_data['args'], indent=2))
print(json_data.get('args', {})) # 送信したパラメータが 'args' に含まれる
except requests.exceptions.RequestException as e:
print(f"エラー: {e}")
POSTリクエスト (フォームデータ)
url = "https://httpbin.org/post"
data = {
"username": "my_user",
"email": "user@example.com"
}
try:
# Content-Type: application/x-www-form-urlencoded で送信される
response = requests.post(url, data=data)
response.raise_for_status()
json_data = response.json()
print("POSTレスポンス (フォームデータ):")
# print(json.dumps(json_data['form'], indent=2))
print(json_data.get('form', {})) # 送信したデータが 'form' に含まれる
except requests.exceptions.RequestException as e:
print(f"エラー: {e}")
POSTリクエスト (JSONデータ)
url = "https://httpbin.org/post"
json_payload = {
"id": 123,
"items": ["apple", "banana"],
"valid": True
}
try:
# json パラメータを使うと自動的にヘッダー (Content-Type: application/json) が設定され、
# データがJSON文字列にエンコードされる
response = requests.post(url, json=json_payload)
response.raise_for_status()
json_data = response.json()
print("POSTレスポンス (JSONデータ):")
# print(json.dumps(json_data['json'], indent=2, ensure_ascii=False))
print(json_data.get('json', {})) # 送信したJSONデータが 'json' に含まれる
# print(f"送信時のヘッダー: {json_data.get('headers', {}).get('Content-Type')}")
except requests.exceptions.RequestException as e:
print(f"エラー: {e}")
その他のリクエストメソッド
url_base = "https://httpbin.org/"
try:
# PUT リクエスト (データの更新/置換)
response_put = requests.put(url_base + "put", data={"key": "new_value"})
response_put.raise_for_status()
# print(f"PUT Status: {response_put.status_code}, Response: {response_put.json().get('form')}")
# DELETE リクエスト (データの削除)
response_delete = requests.delete(url_base + "delete")
response_delete.raise_for_status()
# print(f"DELETE Status: {response_delete.status_code}") # 200 OK なら成功
# PATCH リクエスト (データの一部更新)
response_patch = requests.patch(url_base + "patch", data={"field": "updated"})
response_patch.raise_for_status()
# print(f"PATCH Status: {response_patch.status_code}, Response: {response_patch.json().get('form')}")
# HEAD リクエスト (ヘッダーのみ取得、ボディなし)
response_head = requests.head(url_base + "get")
response_head.raise_for_status()
print(f"HEAD Status: {response_head.status_code}")
print(f"HEAD Content-Type: {response_head.headers.get('Content-Type')}")
# print(f"HEAD Response Body: {response_head.text}") # ボディは空のはず
except requests.exceptions.RequestException as e:
print(f"エラー: {e}")
カスタムヘッダーとタイムアウト
url = "https://httpbin.org/headers"
headers = {
"User-Agent": "MyPythonScript/1.0",
"Accept": "application/json",
"X-Custom-Header": "MyValue"
}
try:
# カスタムヘッダーとタイムアウト (秒) を指定
response = requests.get(url, headers=headers, timeout=5) # 5秒でタイムアウト
response.raise_for_status()
json_data = response.json()
print("レスポンス (カスタムヘッダー):")
# print(json.dumps(json_data['headers'], indent=2))
print(json_data.get('headers', {}))
except requests.exceptions.Timeout:
print("エラー: リクエストがタイムアウトしました。")
except requests.exceptions.RequestException as e:
print(f"エラー: {e}")
データ分析・科学計算 (NumPy, Pandas 基本) 📊
NumPy
と Pandas
はデータ分析や科学計算で広く使われるライブラリです。 (pip install numpy pandas
でインストールが必要です)
NumPy (Numerical Python) – 多次元配列と数値計算
import numpy as np
# NumPy 配列 (ndarray) の作成
# リストから作成
list_data = [1, 2, 3, 4, 5]
arr1d = np.array(list_data)
print(f"1次元配列:\n{arr1d}")
print(f"配列の型: {arr1d.dtype}") # int64 (環境による)
print(f"配列の形状: {arr1d.shape}") # (5,)
# 2次元配列 (行列)
list2d = [[1, 2, 3], [4, 5, 6]]
arr2d = np.array(list2d)
print(f"\n2次元配列:\n{arr2d}")
print(f"形状: {arr2d.shape}") # (2, 3) -> 2行3列
print(f"次元数: {arr2d.ndim}") # 2
print(f"要素数: {arr2d.size}") # 6
# 特定の値で配列を作成
zeros_arr = np.zeros((2, 4)) # 2x4 のゼロ行列
print(f"\nゼロ行列:\n{zeros_arr}")
ones_arr = np.ones((3, 2), dtype=np.float64) # 3x2 の1で埋められた浮動小数点数行列
print(f"\n1で埋められた行列:\n{ones_arr}")
range_arr = np.arange(0, 10, 2) # 0から10未満まで2刻み [0 2 4 6 8]
print(f"\narange配列: {range_arr}")
linspace_arr = np.linspace(0, 1, 5) # 0から1までを5等分 [0. 0.25 0.5 0.75 1. ]
print(f"\nlinspace配列: {linspace_arr}")
random_arr = np.random.rand(2, 3) # 0~1の乱数で 2x3 配列を作成
print(f"\n乱数配列:\n{random_arr}")
# 配列の要素アクセス (スライシング)
print(f"\narr1d[0]: {arr1d[0]}") # 1
print(f"arr1d[1:4]: {arr1d[1:4]}") # [2 3 4]
print(f"arr2d[0, 1]: {arr2d[0, 1]}") # 1行目(0), 2列目(1) -> 2
print(f"arr2d[1, :]: {arr2d[1, :]}") # 2行目(1) の全列 -> [4 5 6]
print(f"arr2d[:, 2]: {arr2d[:, 2]}") # 全行の 3列目(2) -> [3 6]
# 配列の演算 (要素ごとに行われる)
arr_a = np.array([1, 2, 3])
arr_b = np.array([4, 5, 6])
print(f"\n配列の加算: {arr_a + arr_b}") # [5 7 9]
print(f"配列の減算: {arr_b - arr_a}") # [3 3 3]
print(f"配列の乗算: {arr_a * arr_b}") # [ 4 10 18]
print(f"配列の除算: {arr_b / arr_a}") # [4. 2.5 2. ]
print(f"スカラー倍: {arr_a * 2}") # [2 4 6]
print(f"平方根: {np.sqrt(arr_a)}") # [1. 1.41421356 1.73205081]
print(f"指数関数: {np.exp(arr_a)}") # [ 2.71828183 7.3890561 20.08553692]
# 数学関数と統計関数
print(f"\narr2d の合計: {np.sum(arr2d)}") # 21
print(f"arr2d の列ごとの合計: {np.sum(arr2d, axis=0)}") # [5 7 9]
print(f"arr2d の行ごとの合計: {np.sum(arr2d, axis=1)}") # [ 6 15]
print(f"arr2d の平均: {np.mean(arr2d)}") # 3.5
print(f"arr2d の標準偏差: {np.std(arr2d)}") # 1.707825127659933
print(f"arr2d の最大値: {np.max(arr2d)}") # 6
print(f"arr2d の行ごとの最大値: {np.max(arr2d, axis=1)}") # [3 6]
# ブールインデックス参照
bool_idx = arr1d > 3 # [False False False True True]
print(f"\narr1d > 3 の要素: {arr1d[bool_idx]}") # [4 5]
print(f"arr2d > 3 の要素: {arr2d[arr2d > 3]}") # [4 5 6]
# 配列の形状変更
arr_flat = np.arange(6) # [0 1 2 3 4 5]
reshaped_arr = arr_flat.reshape((2, 3)) # 2x3 行列に変換
print(f"\n形状変更後:\n{reshaped_arr}")
print(f"転置行列:\n{reshaped_arr.T}") # T属性で転置
NumPyは高速な数値計算の基盤となり、多くのデータサイエンスライブラリで利用されています。
Pandas – データ操作と分析
import pandas as pd
# Series (1次元配列、ラベル付き) の作成
s_data = [10, 20, 30, 40]
s_index = ['a', 'b', 'c', 'd']
series = pd.Series(data=s_data, index=s_index)
print(f"Pandas Series:\n{series}")
print(f"\nSeries の値: {series.values}") # NumPy 配列
print(f"Series のインデックス: {series.index}")
# ラベルによるアクセス
print(f"\nseries['b']: {series['b']}") # 20
# スライスも可能
print(f"series['a':'c']:\n{series['a':'c']}")
# 辞書から Series 作成
dict_data = {'x': 100, 'y': 200, 'z': 300}
series_from_dict = pd.Series(dict_data)
print(f"\n辞書から作成した Series:\n{series_from_dict}")
# DataFrame (2次元配列、ラベル付きの表形式データ) の作成
df_data = {
'Name': ['Alice', 'Bob', 'Charlie', 'David'],
'Age': [25, 30, 35, 40],
'City': ['Tokyo', 'Osaka', 'Kyoto', 'Fukuoka']
}
df = pd.DataFrame(df_data)
print(f"\nPandas DataFrame:\n{df}")
# インデックスを指定して作成
df_with_index = pd.DataFrame(df_data, index=['emp1', 'emp2', 'emp3', 'emp4'])
print(f"\nインデックス付き DataFrame:\n{df_with_index}")
# 基本情報
print(f"\nDataFrame の形状: {df.shape}") # (4, 4) -> 4行4列
print(f"\nDataFrame の列名: {df.columns}")
print(f"\nDataFrame のインデックス: {df.index}")
# print("\nDataFrame の情報:")
# df.info() # 各列のデータ型や非null数など
# print("\nDataFrame の統計概要:")
# print(df.describe()) # 数値列の基本統計量
# 列へのアクセス
print(f"\nName 列 (Series):\n{df['Name']}")
print(f"\nAge 列と City 列 (DataFrame):\n{df[['Age', 'City']]}")
# 行へのアクセス (loc: ラベルベース, iloc: 整数インデックスベース)
print(f"\n最初の行 (iloc[0]):\n{df.iloc[0]}")
print(f"\n最初の2行 (iloc[:2]):\n{df.iloc[:2]}")
print(f"\nインデックス 'emp2' の行 (loc['emp2']):\n{df_with_index.loc['emp2']}")
print(f"\nインデックス 'emp1' から 'emp3' の行:\n{df_with_index.loc['emp1':'emp3']}")
# 特定の要素へのアクセス
print(f"\n1行目(0), Name列 の値 (iloc): {df.iloc[0, 0]}") # Alice
print(f"\nインデックス 'emp3', Age列 の値 (loc): {df_with_index.loc['emp3', 'Age']}") # 35
# 条件による行の抽出 (ブールインデックス)
print(f"\nAge が 30 より大きい行:\n{df[df['Age'] > 30]}")
print(f"\nCity が 'Tokyo' の行:\n{df[df['City'] == 'Tokyo']}")
# 新しい列の追加
df['Salary'] = [500, 600, 700, 800] # 長さが合っている必要がある
print(f"\nSalary 列を追加した DataFrame:\n{df}")
# 既存列から計算して追加
df['Age_next_year'] = df['Age'] + 1
print(f"\nAge_next_year 列を追加:\n{df}")
# 列の削除
df_dropped = df.drop('Age_next_year', axis=1) # axis=1 は列を指定
# 元の DataFrame を変更する場合は inplace=True を使う
# df.drop('Age_next_year', axis=1, inplace=True)
print(f"\n列を削除した DataFrame (コピー):\n{df_dropped}")
# 欠損値 (NaN) の処理
data_nan = {'A': [1, 2, np.nan, 4], 'B': [5, np.nan, np.nan, 8], 'C': [9, 10, 11, 12]}
df_nan = pd.DataFrame(data_nan)
print(f"\n欠損値を含む DataFrame:\n{df_nan}")
print(f"\n欠損値の確認:\n{df_nan.isnull()}")
print(f"\n欠損値を含む行を削除:\n{df_nan.dropna()}") # デフォルトは行単位 (axis=0)
print(f"\n欠損値を含む列を削除:\n{df_nan.dropna(axis=1)}")
print(f"\n欠損値を特定の値で埋める:\n{df_nan.fillna(value=0)}")
print(f"\n欠損値を列の平均値で埋める:\n{df_nan.fillna(df_nan.mean())}")
# グループ化と集計 (groupby)
data_group = {'Team': ['A', 'B', 'A', 'B', 'A'],
'Score': [10, 15, 12, 18, 13],
'Player': ['P1', 'P2', 'P3', 'P4', 'P5']}
df_group = pd.DataFrame(data_group)
print(f"\nグループ化用 DataFrame:\n{df_group}")
team_group = df_group.groupby('Team')
print(f"\nチームごとの平均スコア:\n{team_group['Score'].mean()}")
print(f"\nチームごとの合計スコア:\n{team_group['Score'].sum()}")
print(f"\nチームごとの人数:\n{team_group.size()}")
# ファイル入出力 (CSV, Excel など)
# df.to_csv('my_dataframe.csv', index=False, encoding='utf-8-sig') # CSV書き出し (index=Falseでインデックスを書き出さない)
# df_from_csv = pd.read_csv('my_dataframe.csv', encoding='utf-8-sig') # CSV読み込み
# print("\nCSVから読み込んだ DataFrame:")
# print(df_from_csv)
# df.to_excel('my_dataframe.xlsx', index=False, sheet_name='Sheet1') # Excel書き出し
# df_from_excel = pd.read_excel('my_dataframe.xlsx', sheet_name='Sheet1') # Excel読み込み
Pandasは、データの読み込み、整形、クリーニング、集計、可視化(他のライブラリと連携)など、データ分析のワークフローで中心的な役割を果たします。
仮想環境 ⚙️
プロジェクトごとに独立したPython環境を作成し、パッケージの依存関係の衝突を防ぎます。Python 3.3以降は venv
モジュールが標準で利用可能です。
venv の基本的な使い方 (コマンドライン)
# 1. 仮想環境の作成 (例: myenv という名前のディレクトリを作成)
# python -m venv <仮想環境ディレクトリ名>
python -m venv myenv
# (Windows の場合)
# python -m venv myenv
# 2. 仮想環境のアクティベート (有効化)
# Linux / macOS (bash/zsh)
source myenv/bin/activate
# Windows (コマンドプロンプト)
myenv\Scripts\activate.bat
# Windows (PowerShell)
# (実行ポリシーの変更が必要な場合がある: Set-ExecutionPolicy RemoteSigned -Scope CurrentUser)
myenv\Scripts\Activate.ps1
# --- アクティベート後のプロンプトには (myenv) のように表示される ---
# 3. パッケージのインストール (仮想環境内にインストールされる)
# (myenv) $ pip install requests pandas numpy
# (myenv) $ pip list # 仮想環境内のパッケージ一覧
# 4. Python スクリプトの実行 (仮想環境の Python が使われる)
# (myenv) $ python my_script.py
# 5. 仮想環境のディアクティベート (無効化)
# (myenv) $ deactivate
# --- (myenv) の表示が消え、元の環境に戻る ---
# 仮想環境ディレクトリ (myenv) は不要になったら削除すれば良い
- プロジェクトごとに仮想環境を作成するのが一般的です。
- 仮想環境をアクティベートした状態で
pip install
を実行すると、その環境内にパッケージがインストールされます。 requirements.txt
ファイルを使って、プロジェクトに必要なパッケージを管理し、他の環境で再現するのに役立ちます。-
# アクティブな仮想環境のパッケージを requirements.txt に書き出す pip freeze > requirements.txt # requirements.txt からパッケージを一括インストール pip install -r requirements.txt
- 仮想環境ディレクトリ自体はバージョン管理システム (Gitなど) に含めず、
requirements.txt
を含めるのが一般的です。
conda
(Anaconda / Miniconda に含まれる) も、特に科学技術計算分野でよく使われるパッケージ管理および環境管理システムです。
コメント