これは、何年か前に Python を学んだときのメモを整理し直したものです。Python 学習者の参考になるよう、基礎的な知識点とよく使うコード例をまとめ、Python をより理解しやすく、使いやすくすることを目的としています。
参考として、次の記事も参照してください。
Pythonコーディングの落とし穴63選:実務で使えるベストプラクティス集
0. 基礎データ型 (Basic Data Types)
- Python は動的型付けで、変数名ではなく値そのものが型を持つ。
value = 10
print(type(value).__name__) # int
value = "ten"
print(type(value).__name__) # str
- 可変 / 不可変の区別を押さえる。
text = "python"
scores = [80, 90]
scores.append(100) # list はその場で変更される
print(text.upper()) # PYTHON
print(scores) # [80, 90, 100]
# text[0] = "P" # TypeError: 'str' object does not support item assignment
- 所属判定は
in/not inで行う。
print("py" in "python") # True
print(2 in [1, 2, 3]) # True
print("age" not in {"name": "Ann"}) # True
- ハッシュ可能な値だけが
dictのキーやsetの要素になれる。
point = {(3, 5): "candidate"} # tuple は辞書キーに使える
tags = {"python", "sql"}
print(point[(3, 5)]) # candidate
print("python" in tags) # True
# bad = {[1, 2]: "point"} # TypeError: unhashable type: 'list'
1. コア構文・式・演算子・真偽値評価 (Core Syntax, Expressions, Operators & Truthiness)
- 代入には
=を使い、比較には==を使う。
score = 90
print(score == 90) # True
score = 95
print(score) # 95
- 基本の値型として
bool、int、float、str、NoneTypeを把握する。
samples = [True, 42, 3.14, "Ada", None]
print([type(item).__name__ for item in samples]) # ['bool', 'int', 'float', 'str', 'NoneType']
- 算術・比較・論理・所属・同一性の演算子を使い分ける。
left = [1, 2]
alias = left
print(7 + 3, 7 // 3, 7 % 3) # 10 2 1
print(7 > 3, 7 == 3) # True False
print(True and False) # False
print("py" in "python") # True
print(left is alias) # True
-
range(start, stop, step)とスライスobj[a:b]は左閉右開で動く。
items = ["a", "b", "c", "d"]
print(list(range(1, 5))) # [1, 2, 3, 4]
print(items[1:3]) # ['b', 'c']
-
input()の戻り値は常にstrである。
user_input = "18" # input() から返ってきた値を想定
print(type(user_input).__name__) # str
age = int(user_input)
print(age + 2) # 20
-
print()の戻り値はNoneである。
result = print("hello") # 1行目の出力: hello
print(result is None) # True
- 空文字列、空コンテナ、
0、0.0、Noneは偽として評価される。
print(bool("")) # False
print(bool([])) # False
print(bool(0)) # False
print(bool("0")) # True
print(bool(None)) # False
2. 制御フロー: 条件分岐・ループ・反復パターン (Control Flow: Conditionals, Loops & Iteration Patterns)
-
if / elif / elseで分岐を書く。
score = 78
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 60:
grade = "C"
else:
grade = "D"
print(grade) # C
-
forは反復向き、whileは終了条件主導の処理向きである。
letters = []
for char in "abc":
letters.append(char) # iterable を 1 要素ずつ処理する
numbers = []
count = 1
while count < 4:
numbers.append(count) # 条件が真のあいだ繰り返す
count += 1
print(letters) # ['a', 'b', 'c']
print(numbers) # [1, 2, 3]
-
breakはループ終了、continueはその周回をスキップ、passはプレースホルダとして使う。
kept = []
for n in range(5):
if n == 1:
continue # 1 は飛ばす
if n == 3:
break # 3 でループを終了する
kept.append(n)
if True:
pass # まだ実装しない場所の占位
print(kept) # [0, 2]
-
range()、enumerate()、zip()、reversed()、dict.items()は頻出の補助ツールである。
names = ["ann", "bob"]
scores = [90, 85]
user = {"name": "Ann", "age": 22}
print(list(range(3))) # [0, 1, 2]
print(list(enumerate(names, start=1))) # [(1, 'ann'), (2, 'bob')]
print(list(zip(names, scores))) # [('ann', 90), ('bob', 85)]
print(list(reversed(names))) # ['bob', 'ann']
print(list(user.items())) # [('name', 'Ann'), ('age', 22)]
- ガード節を使うとネストを減らせる。
def reciprocal(x):
if x == 0:
return None # 先に特殊ケースを返す
return 1 / x
print(reciprocal(4)) # 0.25
print(reciprocal(0)) # None
3. 文字列・文字・変換・エンコーディング (Strings, Characters, Conversion & Encoding)
- Python の「1 文字」は独立した
charではなく、長さ 1 の文字列である。
ch = "A"
print(type(ch).__name__) # str
print(len(ch)) # 1
- 文字列は immutable sequence である。
text = "python"
upper_text = text.upper() # 新しい文字列を返す
print(text) # python
print(upper_text) # PYTHON
# text[0] = "P" # TypeError: 'str' object does not support item assignment
- 文字列ではインデックス、スライス、連結、繰り返し、所属判定が頻出である。
text = "Python"
print(text[0]) # P
print(text[1:4]) # yth
print("Py" + "3") # Py3
print("Ha" * 2) # HaHa
print("yth" in text) # True
-
lower()、upper()、strip()、replace()、split()、splitlines()、join()、find()、count()、startswith()、endswith()、isdigit()、isalpha()、isalnum()、isspace()はよく使う。
text = " Python 3 "
print(text.lower()) # python 3
print(text.upper()) # PYTHON 3
print(text.strip()) # Python 3
print(text.replace("3", "3.11")) # Python 3.11
print("a,b,c".split(",")) # ['a', 'b', 'c']
print("a\nb".splitlines())
# ['a',
# 'b']
print("-".join(["a", "b", "c"])) # a-b-c
print("banana".find("na"), "banana".count("a")) # 2 3
print("python".startswith("py"), "python".endswith("on")) # True True
print("7".isdigit(), "A".isalpha(), "A1".isalnum(), " ".isspace()) # True True True True
-
ord()、chr()、str()、int('7')などの変換関数を押さえる。
print(ord("A")) # 65
print(chr(65)) # A
print(str(42)) # 42
print(int("7")) # 7
- 文字列フォーマットはまず f-string を使えるようにする。
name = "Ann"
score = 93.456
print(f"{name}: {score:.2f}") # Ann: 93.46
4. コンテナ・内包表記・ソート・探索 (Containers, Comprehensions, Sorting & Searching)
- リスト内包表記は
[expr for x in iterable if condition]の形で書く。
squares = [x * x for x in range(6) if x % 2 == 0]
print(squares) # [0, 4, 16]
- 辞書内包表記は
{k: v for ...}の形で書く。
name_lengths = {name: len(name) for name in ["ann", "bob", "cindy"]}
print(name_lengths) # {'ann': 3, 'bob': 3, 'cindy': 5}
- 集合内包表記は
{expr for x in iterable}の形で書く。
even_square_set = {x * x for x in range(6) if x % 2 == 0}
print(even_square_set) # {0, 4, 16}
-
sorted(x)は新しい値を返し、x.sort()はその場で並べ替えてNoneを返す。
nums = [3, 1, 2]
sorted_nums = sorted(nums)
sort_result = nums.sort() # nums 自体が書き換わる
print(sorted_nums) # [1, 2, 3]
print(nums) # [1, 2, 3]
print(sort_result) # None
- 並べ替えでは
key=とreverse=をよく使う。
rows = [
{"name": "ann", "age": 22},
{"name": "bob", "age": 19},
{"name": "cindy", "age": 25},
]
print(sorted(rows, key=lambda row: row["age"])) # [{'name': 'bob', 'age': 19}, {'name': 'ann', 'age': 22}, {'name': 'cindy', 'age': 25}]
print(sorted(rows, key=lambda row: row["name"], reverse=True)) # [{'name': 'cindy', 'age': 25}, {'name': 'bob', 'age': 19}, {'name': 'ann', 'age': 22}]
- 線形探索、
in、dict/setによるハッシュ探索、二分探索を状況で使い分ける。
def linear_search(items, target):
for index, value in enumerate(items):
if value == target:
return index
return -1
def binary_search(sorted_items, target):
left = 0
right = len(sorted_items) - 1
while left <= right:
mid = (left + right) // 2
guess = sorted_items[mid]
if guess == target:
return mid
if guess < target:
left = mid + 1
else:
right = mid - 1
return -1
items = [10, 20, 30, 40]
lookup = {"ann": 95, "bob": 88}
print(linear_search(items, 30)) # 2
print(20 in items) # True
print(lookup["ann"]) # 95
print(binary_search([1, 3, 5, 7, 9], 7)) # 3
-
dict.get()、keys()、values()、items()、update()、pop()、setdefault()は頻出メソッドである。
profile = {"name": "Ann", "age": 22}
print(profile.get("city", "unknown")) # unknown
print(list(profile.keys())) # ['name', 'age']
print(list(profile.values())) # ['Ann', 22]
print(list(profile.items())) # [('name', 'Ann'), ('age', 22)]
profile.update({"city": "BJ"})
print(profile.pop("age")) # 22
print(profile.setdefault("country", "CN")) # CN
print(profile) # {'name': 'Ann', 'city': 'BJ', 'country': 'CN'}
5. 関数・再帰・高階関数・状態の受け渡し (Functions, Recursion, Higher-Order Functions & State Passing)
- 関数は「入力 -> 処理 -> 出力」の単位として考える。
def add_bonus(score):
bonus = 5 # 入力を受け取り、処理して返す
return score + bonus
print(add_bonus(90)) # 95
-
returnがなければ戻り値はNoneになる。
def hello():
print("hello") # 1行目の出力: hello
result = hello()
print(result is None) # True
- 位置引数、キーワード引数、デフォルト引数、
*args、**kwargsを使い分ける。
def show(name, greeting="Hello", *tags, punctuation="!", **options):
print(f"{greeting}, {name}{punctuation}") # 1行目の出力: Hi, Ann?
print(tags) # 2行目の出力: ('python', 'sql')
print(options) # 3行目の出力: {'lang': 'en'}
show("Ann", "Hi", "python", "sql", punctuation="?", lang="en")
-
lambdaは短い無名関数に向いている。
squared = list(map(lambda x: x * x, [1, 2, 3, 4]))
print(squared) # [1, 4, 9, 16]
- 再帰では base case を置き、毎回問題を小さくする。
def factorial(n):
if n == 1:
return 1 # base case
return n * factorial(n - 1)
print(factorial(5)) # 120
- 高階関数は、関数を受け取るか返す関数である。
def apply_twice(func, value):
return func(func(value))
def double(x):
return x * 2
print(apply_twice(double, 3)) # 12
- 状態は引数で受け取り、戻り値で返し、必要なら
dict・tuple・dataclass・インスタンスにまとめる。
from dataclasses import dataclass
@dataclass
class PipelineContext:
user_id: str
retry_count: int
is_debug: bool
def next_context(context, retry_increment):
return PipelineContext(
user_id=context.user_id,
retry_count=context.retry_count + retry_increment,
is_debug=context.is_debug,
)
ctx = PipelineContext("u001", 0, True)
print(next_context(ctx, 1)) # PipelineContext(user_id='u001', retry_count=1, is_debug=True)
6. ファイル・例外・モジュール・エラー処理 (Files, Exceptions, Modules & Error Handling)
- ファイル処理の入口は
open(path, mode, encoding=...)である。
with open("sample.txt", "w", encoding="utf-8") as file_obj:
written = file_obj.write("first line\n") # 1 行を書き込む
print(written) # 11
-
r/w/a/xの意味を押さえる。
# r: 読み込み
# w: 上書き書き込み
# a: 追記
# x: 未存在時だけ新規作成
with open("sample.txt", "a", encoding="utf-8") as file_obj:
file_obj.write("second line\n") # 既存ファイルの末尾に追記する
# with open("new-only.txt", "x", encoding="utf-8") as file_obj:
# file_obj.write("created once") # 既に存在すると FileExistsError
- ファイルは
with open(...) as f:の context manager で扱う。
with open("sample.txt", "r", encoding="utf-8") as file_obj:
content = file_obj.read()
print(repr(content)) # 'first line\nsecond line\n'
print(file_obj.closed) # True
- 例外処理の基本形は
try / except / else / finallyである。
def parse_age(text):
try:
age = int(text)
except ValueError as exc:
print(f"bad input: {exc}") # 異常時の出力
else:
print(age) # 正常時の出力
finally:
print("done") # 後始末の場所
parse_age("18")
# 1行目: 18
# 2行目: done
parse_age("abc")
# 1行目: bad input: invalid literal for int() with base 10: 'abc'
# 2行目: done
- 予期した例外だけを、できるだけ具体的な型で捕まえ、黙って飲み込まない。
from pathlib import Path
def load_text(path_str):
try:
return Path(path_str).read_text(encoding="utf-8")
except FileNotFoundError as exc:
raise RuntimeError(f"missing file: {path_str}") from exc
# load_text("missing.txt") # RuntimeError: missing file: missing.txt
-
ValueError、TypeError、KeyError、IndexError、ZeroDivisionError、FileNotFoundErrorは頻出例外である。
error_names = []
tests = [
lambda: int("abc"),
lambda: "1" + 1,
lambda: {"a": 1}["b"],
lambda: [][1],
lambda: 1 / 0,
lambda: open("missing.txt", "r", encoding="utf-8").read(),
]
for func in tests:
try:
func()
except (ValueError, TypeError, KeyError, IndexError, ZeroDivisionError, FileNotFoundError) as exc:
error_names.append(type(exc).__name__)
print(error_names) # ['ValueError', 'TypeError', 'KeyError', 'IndexError', 'ZeroDivisionError', 'FileNotFoundError']
- モジュールの読み込みでは
import math、from math import sqrt、import mycode as mなどを使う。
import math
from math import sqrt
import mycode as m
print(math.ceil(2.1)) # 3
print(sqrt(16)) # 4.0
print(m.is_prime(29)) # True
7. クラスとオブジェクト指向 (Classes & Object-Oriented Programming)
-
classでクラスを定義し、__init__で初期化処理を書く。
class Golem:
def __init__(self, name):
self.name = name
g = Golem("Clay")
print(g.name) # Clay
-
selfは現在のインスタンスを指す。
class Greeter:
def __init__(self, name):
self.name = name
def say_hi(self):
return f"Hi, I am {self.name}."
print(Greeter("Stone").say_hi()) # Hi, I am Stone.
- インスタンス属性とクラス属性は区別して使う。
class Golem:
population = 0
def __init__(self, name):
self.name = name
Golem.population += 1 # クラス属性を更新する
g1 = Golem("A")
g2 = Golem("B")
print(g1.name, g2.name) # A B
print(Golem.population) # 2
- メソッドは、クラスの中で定義された関数である。
class Calculator:
def double(self, x):
return x * 2
calc = Calculator()
print(calc.double(5)) # 10
print(callable(Calculator.double)) # True
- 継承を使うと、子クラスが親クラスの機能を再利用できる。
class Golem:
def say_hi(self):
return "hi"
class RunningGolem(Golem):
def run(self):
return "running"
g = RunningGolem()
print(g.say_hi(), g.run()) # hi running
- override で子クラスが親クラスの振る舞いを上書きできる。
class Parent:
def say(self):
return "parent"
class Child(Parent):
def say(self):
return "child"
print(Child().say()) # child
-
@propertyを使うと、メソッドを属性のように読める。
class Circle:
def __init__(self, r):
self.r = r
@property
def area(self):
return 3.14159 * self.r * self.r
c = Circle(2)
print(c.area) # 12.56636
8. 発展 Python: イテレータ・ジェネレータ・デコレータ・正規表現 (Advanced Python: Iterators, Generators, Decorators & Regular Expressions)
- iterator は
next()で 1 つずつ値を取り出す。
it = iter([10, 20, 30])
print(next(it)) # 10
print(next(it)) # 20
- generator は
yieldを使って値を遅延生成する。
def counter(start, stop):
while start <= stop:
yield start # ここで 1 つずつ値を返す
start += 1
print(list(counter(3, 5))) # [3, 4, 5]
- decorator は関数を受け取り、別の関数で包んで返す。
from functools import wraps
def trace(func):
@wraps(func) # 元の関数名や docstring を保つ
def wrapper(*args, **kwargs):
print("calling", func.__name__) # 呼び出し前にログを出す
return func(*args, **kwargs)
return wrapper
@trace
def add(x, y):
return x + y
print(add(2, 3))
# 1行目: calling add
# 2行目: 5
- regex はマッチ、抽出、置換に使う。
import re
text = "email: ann01@test.com"
print(re.search(r"ann01@test\.com", text).group()) # ann01@test.com
print(re.findall(r"\d+", "a12b300")) # ['12', '300']
print(re.sub(r"\s+", " ", "too many spaces")) # too many spaces
- iterator / generator はデータストリーム、遅延評価(lazy evaluation)、段階的計算に向いている。
def read_numbers(lines):
for line in lines:
yield int(line) # 必要になった時点で 1 つずつ変換する
stream = read_numbers(["1", "2", "3", "4"])
print(next(stream)) # 1
print(sum(stream)) # 9
- decorator は logging、timing、caching、authorization などの横断的処理に使われる。
from functools import lru_cache
@lru_cache(maxsize=None) # caching の例
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
first = fib(10)
second = fib(10) # 2 回目はキャッシュが使われる
print(first, second) # 55 55
print(fib.cache_info().hits > 0) # True
9. 標準ライブラリと実用的な問題解決パターン (Standard Library & Practical Problem-Solving Patterns)
-
collectionsではCounter、defaultdict、dequeをよく使う。
counts = Counter("banana")
groups = defaultdict(list)
groups["BJ"].append("Ann")
queue = deque([1, 2, 3])
print(counts["a"]) # 3
print(dict(groups)) # {'BJ': ['Ann']}
print(queue.popleft()) # 1
-
itertoolsではproduct、combinations、permutations、chainが頻出である。
from itertools import chain, combinations, permutations, product
print(list(product([1, 2], ["A", "B"]))) # [(1, 'A'), (1, 'B'), (2, 'A'), (2, 'B')]
print(list(combinations(["a", "b", "c"], 2))) # [('a', 'b'), ('a', 'c'), ('b', 'c')]
print(list(permutations([1, 2, 3], 2))) # [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
print(list(chain([1, 2], [3, 4]))) # [1, 2, 3, 4]
-
mathではsqrt、ceil、floor、log、isclose、factorialを押さえる。
from math import ceil, factorial, floor, isclose, log, sqrt
print(sqrt(16)) # 4.0
print(ceil(2.1), floor(2.9)) # 3 2
print(log(8, 2)) # 3.0
print(isclose(0.1 + 0.2, 0.3)) # True
print(factorial(5)) # 120
-
datetimeではdatetime、date、timedelta、strptime、strftimeを使う。
from datetime import date, datetime, timedelta
dt = datetime.strptime("2026-04-03 09:30", "%Y-%m-%d %H:%M")
next_day = date(2026, 4, 3) + timedelta(days=1)
print(dt.strftime("%Y-%m-%d %H:%M")) # 2026-04-03 09:30
print(next_day.isoformat()) # 2026-04-04
-
bisectはソート済み配列の二分探索や挿入位置計算に使う。
from bisect import bisect_left
sorted_nums = [1, 3, 5, 7, 9]
print(bisect_left(sorted_nums, 4)) # 2
-
heapqは最小ヒープとして top-k や優先度付き処理に使う。
import heapq
heap = [5, 1, 3, 9]
heapq.heapify(heap)
print(heapq.heappop(heap)) # 1
print(heapq.nsmallest(2, [8, 2, 6, 1, 5])) # [1, 2]
-
pathlibは現代的なパス操作に向いている。
from pathlib import Path
path = Path("logs") / "app.txt"
print(path.as_posix()) # logs/app.txt
print(path.suffix) # .txt
-
functoolsではlru_cache、partial、wrapsが実用的である。
from functools import lru_cache, partial, wraps
def trace(func):
@wraps(func) # 元の関数名を保つ
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@trace
def square(x):
return x * x
@lru_cache(maxsize=None)
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
base_two_int = partial(int, base=2)
print(square.__name__) # square
print(fib(10)) # 55
print(base_two_int("1010")) # 10