株式会社Good Labでエンジニアをしている コータロー です。
日々、Java・SQL・Gitなどの技術情報や、新人エンジニア向けの学習ノウハウ、
AI活用についての情報を発信しています。
Good Labについて気になった方は、コーポレートサイトもぜひご覧ください。
▶コーポレートサイト
はじめに
Java の経験があっても、Python で書かれた既存ツールを初めて開くと、// や is、[x for x in ...] のような見慣れない書き方で手が止まりがちです。
このシリーズは Java は書けるが Python は未経験で、既存の Python ツールを読んで直す必要が出た人 向けの入門で、私自身の学習教材も兼ねています。
| 回 | テーマ |
|---|---|
| 第1回(本記事) | 基礎文法 ― Java との違いで覚える |
| 第2回 | 関数・例外・モジュール ― def の書き方と、ツールの骨格を読むための知識 |
| 第3回 | Excel の管理表と pom.xml を突き合わせて、差分を GUI に出すツールを作る |
| 第4回 | 既存ツールを読んで直す(ライブラリの見分け方・EXE 化・Windows での注意・安全な直し方) |
動作環境:Python 3.14.6。記事中のコードはすべて 3.14.6 で実行し、出力とエラーメッセージを確認済みです。3.9 以前では動かない書き方には注記を付けます(3.9 は 2025年10月にサポート終了)。関数定義・例外処理・import は第2回で扱います。
1. Java との対比表
| 項目 | Java | Python |
|---|---|---|
| ブロック | { } |
インデント(字下げ) |
| 文の終わり / コメント |
; / //
|
改行 / #
|
| 実行の起点 |
main メソッド |
ファイルの先頭から順に実行 |
| 変数宣言 | int x = 1; |
x = 1(型宣言なし) |
| 整数の範囲 |
int 32bit / long 64bit |
int に上限なし |
7 / 2 |
3 |
3.5(常に float) |
| 整数除算 / べき乗 |
7 / 2 / Math.pow(2, 10)
|
7 // 2 / 2 ** 10
|
| 論理演算 |
&& || !
|
and or not
|
| 真偽値・null |
true false null
|
True False None
|
| 値が等しいか | a.equals(b) |
a == b |
| 同一オブジェクトか | a == b |
a is b |
| インクリメント | i++ |
i += 1(++ はない) |
| 三項演算子 | c ? a : b |
a if c else b |
switch |
switch 文 |
match 文 |
2. インデントでブロックを表す
Java(main メソッド内の抜粋)の次の処理を、Python で書いてみます。
int score = 75;
if (score >= 60) {
System.out.println("合格");
System.out.println("おめでとう");
}
System.out.println("判定終了");
score = 75
if score >= 60:
print("合格")
print("おめでとう")
print("判定終了")
実行結果
合格
おめでとう
判定終了
- クラスも
mainも不要で、python3 ファイル名.pyで先頭から実行されます - 条件の
( )は不要、行末に:を付けます - 同じ深さで字下げされた行がひとつのブロック です(PEP 8 はスペース4つを推奨)
- 空のブロックは書けないので、何もしないときは
passと書きます
ハマりどころ:インデントのずれ
字下げが揃っていないと IndentationError: unexpected indent、タブとスペースが混ざると TabError です。エディタは「タブをスペース4つに変換」に設定します。
本当に怖いのは エラーにならないずれ です。
score = 50
if score >= 60:
print("合格")
print("判定終了") # うっかり字下げして if の中に入った
実行結果:何も表示されません。判定終了 まで if の中に入ったからです。字下げがそのまま処理の範囲 です。
3. 変数と型
型宣言はなく、代入した時点で変数が作られます。: int の部分は 型ヒント で、既存ツールでもよく見ます。
count: int = 10
names: list[str] = ["Taro", "Hanako"]
limit: int | None = None # int または None
print(type(count), type(0.5), type(True))
count = "ten" # ヒントと違う型を再代入してもエラーにならない
print(type(count), names, limit)
実行結果
<class 'int'> <class 'float'> <class 'bool'>
<class 'str'> ['Taro', 'Hanako'] None
これが 動的型付け です。型を持つのは値で、変数は値を指す名札です。型ヒントは実行時には強制されず、mypy などの静的チェッカーや IDE が使う注釈です。一方で暗黙の型変換は少なく、"1" + 1 は "11" にならず TypeError: can only concatenate str (not "int") to str です。命名は snake_case、定数は大文字で書く慣習だけで、final に当たる仕組みはありません。
3.9 以前の注記:
int | Noneは 3.10 以降の書き方で、3.9 ではTypeErrorになります。typing.Optional[int]と書きます。
4. 数値
print(2 ** 100)
print(7 / 2, 6 / 2)
print(7 // 2, -7 // 2)
print(-7 % 3)
print(round(2.5), round(3.5))
実行結果
1267650600228229401496703205376
3.5 3.0
3 -4
2
2 4
-
intに上限はなく、2 ** 100もオーバーフローしません -
/は常に float を返します(6 / 2も3.0) -
//と%は床除算(小さい方向に丸める)です。Java では-7 / 2は-3、-7 % 3は-1ですが、Python は-4と2。Java のMath.floorDiv/Math.floorModと同じ挙動です -
round()は 偶数丸め でround(2.5)は2(Java のMath.round(2.5)は3)
++ はなく i++ は SyntaxError: invalid syntax です。厄介なのは ++i で、符号 + が2つ付いた式として エラーにならず値も増えません。
5. 文字列
シングルクォートとダブルクォートは同じ意味です。char 型はなく、1文字も str です。値の埋め込みには f-string を使います。
name = "Taro"
age = 25
print(f"{name}さんは{age + 1}歳になります")
print(f"{1234.5:,.1f}円 / {age:05d}")
line = " apple,banana,cherry "
items = line.strip().split(",")
print(items)
print(" / ".join(items))
print("banana" in line, "Python".find("th"), len("こんにちは"))
実行結果
Taroさんは26歳になります
1,234.5円 / 00025
['apple', 'banana', 'cherry']
apple / banana / cherry
True 2 5
{} には式を書け、: の後ろは書式指定です。String.join(sep, list) は sep.join(list)、contains は in、indexOf は find()(ないと -1)、length() は len() 関数に当たります。
スライス [開始:終了] で部分を取り出せます。終了位置は含まず(substring と同じ)、負の数は末尾から数えます。
s = "Python"
print(s[0], s[-1], s[0:2], s[2:], s[:-2], s[::-1])
実行結果
P n Py thon Pyth nohtyP
スライスはリストにも使えます。文字列は不変で、s[0] = "J" は TypeError: 'str' object does not support item assignment です。
6. 真偽値と None
True / False / None は先頭が大文字で、true と書くと NameError です。
flag = true
実行結果(パスは環境によって異なります)
Traceback (most recent call last):
File "/path/to/name_error.py", line 1, in <module>
flag = true
^^^^
NameError: name 'true' is not defined. Did you mean: 'True'?
エラー箇所の ^^^^ と Did you mean の候補は、3.9 では表示されません。
どんな値でも条件に書け、空やゼロは偽になります(truthiness)。
for v in [0, "", [], {}, None, "0", [0], -1]:
print(repr(v), bool(v))
実行結果
0 False
'' False
[] False
{} False
None False
'0' True
[0] True
-1 True
このため既存ツールでは if items:(空でなければ)、if not name:(空または None なら)をよく見ます。
and / or は真偽値ではなく オペランドそのもの を返すので、name = input_name or "default" は「空なら既定値」です。
7. == と is ― Java と逆に見える
Python の == は Java の equals()、is は Java の == に当たります。
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b, a is b)
x, y = int("100"), int("100")
p, q = int("1000"), int("1000")
print(x is y, p == q, p is q)
実行結果
True False
True True False
文字列比較も == で正しく書けます。is で値を比べるのは誤りです。CPython は -5〜256 の整数をキャッシュするため 100 同士は is でも True、1000 だと False です(実装依存)。小さい値のテストだけ通る典型的なバグです。
is は x is None / x is not None にだけ使う と覚えます。x is 1000 とリテラルを比べると SyntaxWarning: "is" with 'int' literal. Did you mean "=="? が出ます。
8. コレクション
| Python | 近い Java | 変更 | 書き方 |
|---|---|---|---|
list |
ArrayList |
可 | [1, 2] |
tuple |
List.of(...)(不変) |
不可 | (1, 2) |
dict |
HashMap(順序は LinkedHashMap 相当) |
可 | {"a": 1} |
set |
HashSet |
可 | {1, 2} |
要素の型は型ヒントで list[str] や dict[str, int] と書きます。
fruits = ["apple", "banana"]
fruits.append("cherry")
print(fruits, len(fruits), fruits[-1])
print(fruits.pop(), fruits)
x, y = (3, 4) # tuple のアンパック
print(x, y, type((1,)), type((1)))
print({1, 2} & {2, 3}, type({}))
実行結果
['apple', 'banana', 'cherry'] 3 cherry
cherry ['apple', 'banana']
3 4 <class 'tuple'> <class 'int'>
{2} <class 'dict'>
-
get(i)はfruits[i]、size()はlen()です -
fruits.sort()は元を並べ替えてNoneを返します。新しいリストはsorted(fruits)で作ります - 要素1つの tuple は
(1,)とカンマが必要です -
空の
{}は dict で、空の set はset()です。set の表示順は保証されません
ages: dict[str, int] = {"Taro": 25, "Hanako": 30}
ages["Jiro"] = 20
print(ages["Taro"], ages.get("Saburo"), ages.get("Saburo", 0))
print("Hanako" in ages)
for name, age in ages.items():
print(name, age)
実行結果
25 None 0
True
Taro 25
Hanako 30
Jiro 20
- 存在しないキーを
ages["Saburo"]で取るとnullではなくKeyError: 'Saburo'です。get()の2引数版はgetOrDefault相当 -
inはcontainsKey、.items()はキーと値の組 - dict は 挿入順の保持が言語仕様で保証 されています(3.7 以降)
9. 制御構文
score = 72
if score >= 80:
grade = "A"
elif score >= 60:
grade = "B"
else:
grade = "C"
label = "合格" if score >= 60 else "不合格"
print(grade, label, 0 <= score < 100)
実行結果
B 合格 True
-
else ifではなくelifです - 三項演算子は
値1 if 条件 else 値2で、条件が真ん中 です -
0 <= score < 100のように比較を連結できます
if 内で代入した grade を外で使えるとおり、if や for は 新しいスコープを作りません。
match ― Java の switch に当たる
1つの値を候補と比べるなら match 文を使えます。
for command in ["start", "stop", "pause", "exit"]:
match command:
case "start":
print("開始")
case "stop" | "exit":
print("終了")
case _:
print(f"不明なコマンド: {command}")
実行結果
開始
終了
不明なコマンド: pause
終了
-
フォールスルーはなく
breakも不要で、最初に一致したcaseだけが動きます - 複数の値は
|でまとめ、case _:がdefaultです -
case LIMIT:のような裸の名前は比較ではなく代入 で、何にでも一致します(後ろにcaseが続くとSyntaxError)。定数はリテラルかColor.REDのようなドット付きの名前で書きます
3.9 以前の注記:
match文は 3.10 以降です。3.9 ではSyntaxErrorになるのでif/elifを並べます。
for / range / enumerate / zip
for は Java の拡張 for に近く、回数指定は range(開始, 終了, 増分)(終了値は含まない)です。インデックスも欲しいときは enumerate、2つのリストを並べるときは zip です。
for i in range(1, 10, 3):
print(i)
for i, fruit in enumerate(["apple", "banana"], start=1):
print(f"{i}: {fruit}")
for name, score in zip(["Taro", "Hanako", "Jiro"], [80, 95]):
print(name, score)
print(i)
実行結果
1
4
7
1: apple
2: banana
Taro 80
Hanako 95
2
zip は 短いほうに合わせて黙って終わる ので Jiro が無視されています。最後の print(i) はループ変数がループ後も残る例です。
zip(a, b, strict=True) なら長さ違いで ValueError: zip() argument 2 is shorter than argument 1 です。ただし片方が尽きた時点で気づくので、それまでの要素は処理済み です。困る場合はループ前に len() を比べます。
3.9 以前の注記:
strict引数は 3.10 以降で、3.9 ではTypeErrorになります。
while / break / continue
n = 0
while n < 10:
n += 1
if n % 2 == 0:
continue
if n > 7:
break
print(n)
実行結果
1
3
5
7
使い方は Java と同じで、do-while はありません。ループ直後の else: は「break せずに回り終えたときだけ実行」です。
10. 内包表記を読む
既存ツールで最も戸惑う内包表記は、まず読めれば十分です。
nums = [1, 2, 3, 4, 5]
print([n * n for n in nums])
print([n for n in nums if n % 2 == 0])
print(["偶" if n % 2 == 0 else "奇" for n in nums])
print({w: len(w) for w in ["apple", "kiwi"]})
print([x for row in [[1, 2], [3, 4]] for x in row])
実行結果
[1, 4, 9, 16, 25]
[2, 4]
['奇', '偶', '奇', '偶', '奇']
{'apple': 5, 'kiwi': 4}
[1, 2, 3, 4]
for から読み、if を見て、最後に先頭の式を見る のがコツです。2行目は「nums の各 n のうち偶数を集める」と読み、Java の stream().filter(...) に当たります。
-
末尾の
ifは絞り込み、先頭のA if 条件 else Bは三項演算子による変換(絞り込まない) -
forが2つあれば 左から順にネストした for として読む
11. ハマりどころ
代入が参照のコピーなのは Java と同じですが、リストの初期化で思わぬ形で表れます。
a = [1, 2, 3]
b = a
b.append(4)
c = a.copy()
c.append(5)
print(a, c)
grid = [[0] * 3] * 2
grid[0][0] = 9
print(grid)
grid_ok = [[0] * 3 for _ in range(2)]
grid_ok[0][0] = 9
print(grid_ok)
実行結果
[1, 2, 3, 4] [1, 2, 3, 4, 5]
[[9, 0, 0], [9, 0, 0]]
[[9, 0, 0], [0, 0, 0]]
b = a は同じリストに別名を付けるだけなので、別物が欲しいなら copy()(浅いコピー)です。[[0] * 3] * 2 は同じ内側リストを2回並べたものなので、2次元リストは内包表記で作ります(_ は使わない変数の慣習名)。
本記事のハマりどころをまとめます。
| 症状 | 原因 | 対処 |
|---|---|---|
| 処理範囲がずれる | 字下げのずれ | スペース4つに統一し所属を確認 |
結果が 3.0 になる |
/ は常に float |
整数なら //
|
| 負数の割り算が Java と合わない |
// % は床除算 |
floorDiv / floorMod 相当と理解 |
| 大きな数で比較が失敗 |
is で値を比較 |
値は ==、is は None 専用 |
0 が「未設定」扱い |
truthiness |
is None で判定 |
| データが黙って欠ける |
zip は短いほうで終わる |
strict=True か事前に len()
|
| 片方の変更がもう片方に出る | 参照の共有 |
copy() / 内包表記 |
確認問題
問1
難易度:⭐
出力を答えてください。
print(7 / 2)
print(7 // 2)
print(-7 // 2)
print(-7 % 3)
模範解答
3.5
3
-4
2
/ は常に float。// と % は床除算なので、負数では Java(-3 と -1)と結果が変わります。
問2
難易度:⭐⭐
内包表記を使わない for 文に書き換え、出力も答えてください。
names = ["Taro", "Hanako", "Jiro", "Saburo"]
result = {name: len(name) for name in names if len(name) >= 5}
print(result)
模範解答
names = ["Taro", "Hanako", "Jiro", "Saburo"]
result: dict[str, int] = {}
for name in names:
if len(name) >= 5:
result[name] = len(name)
print(result)
実行結果
{'Hanako': 6, 'Saburo': 6}
末尾の if は絞り込みです。dict は挿入順を保持するので、元のリストの順に並びます。
問3
難易度:⭐⭐⭐
None のときだけ「未設定」と表示したいコードです。出力を答え、バグを直してください。
for count in [None, 0, 3]:
if not count:
print("未設定")
else:
print(f"{count}件")
模範解答
未設定
未設定
3件
0 も偽なので「0件」が「未設定」になります。None だけを判定するには is None を使います。
for count in [None, 0, 3]:
if count is None:
print("未設定")
else:
print(f"{count}件")
実行結果
未設定
0件
3件
次回予告
次回は 第2回:関数・例外・モジュール。def、try / except、import など、ツールの骨格を読むための知識を扱います。
参考
- Python チュートリアル - データ構造
- Python チュートリアル - その他の制御フローツール
- Python 標準ライブラリ - 組み込み型
- Status of Python versions
- PEP 8 – Style Guide for Python Code
@kotaro_ai_lab
AI活用や開発効率化について発信しています。フォローお気軽にどうぞ!