1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Java経験者のためのPython入門 第1回】基礎文法 ― インデント・型・コレクション・制御構文をJavaとの違いで覚える

1
Posted at

株式会社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 など、ツールの骨格を読むための知識を扱います。

参考


@kotaro_ai_lab
AI活用や開発効率化について発信しています。フォローお気軽にどうぞ!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?