+ 作るログイン
図を読み込んでいます…
1 / 20
JS から来た人の Python ― どこから来て、なぜ動くのか / 全19章

Python 03:基本の文法 ― JS と並べて、違う理由まで

発行
アニメモ公式
版
第1版
改訂
コマ
全20

JavaScript が書ける人のための、Python の基本の文法です。波かっこの代わりの字下げ、let も const も無い変数、int・float・str・bool・None の型、勝手に型を変えない理由、f-string、=== が無い代わりの == と is、空の list が偽になる真偽の判定、and・or・not と三項演算子、コメントと print までを、同じプログラムを JS と並べて1つずつ比べます。

JS は書ける。では Python は何が違う?

第1章と第2章で、Python というインタプリタ(python3 という実行ファイル)を手元に入れ、python3 main.py で動かせるようになりました。いよいよ中身を書きます。

図の左右は、どちらも「東京の気温が30度以上なら『東京は暑い: 31度』と表示する」だけのプログラムです。左が JavaScript(Node.js で動かす)、右が Python です。

見比べると、似ているところと違うところがすぐに目に入ります。

見るところJavaScriptPython
変数を作るconst / let を書く何も書かない
条件if (…) { と丸かっこ・波かっこif …: とコロン
「かつ」&&and
等しくない!==!=
表示console.log(…)print(…)
文の終わり;(省略もできる)何も書かない
コメント//#

この章では、こうした違いを「Python ではこう書く」と暗記するのではなく、なぜそう書くのかを添えて1つずつ見ていきます。理由が分かると、忘れても思い出せますし、JS の癖で書いてエラーになったときに「ああ、あれか」とすぐ気づけます。

扱うのは、字下げ(ブロック)、変数、基本の型、文字列への埋め込み(f-string)、比較(== と is)、真偽の判定、and・or・not、コメントと print です。最後に、本全体で育てていく天気のコマンド tenki の最初の1ファイルを書きます。

※2026年9月時点(Python 3.13)の情報です。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 1 / 20
  • JS は書ける。では Python は何が違う?
  • JavaScript(Node.js)
  • Python
  • // tenki.js
  • # tenki.py
  • const city = "東京";
  • city = "東京"
  • let temp = 31;
  • temp = 31
  • if (temp >= 30 && city !== "") {
  • if temp >= 30 and city != "":
  • console.log(`${city}は暑い: ${temp}度`);
  • print(f"{city}は暑い: {temp}度")
  • } else {
  • else:
  • console.log("ふつう");
  • print("ふつう")
  • }
  • どちらも「東京は暑い: 31度」と表示する。やっていることは同じで、書き方だけが違う
  • この章は、その「書き方の違い」と「違う理由」を1つずつ見ていく
  • ひらめき
  • 同じことをする2つのプログラム。形は似ているが、記号の数がかなり違う。

一言でいうと:記号を減らし、字下げと英語で書く

Python の文法を一言でいうと、記号を減らして、字下げと英単語で書く言語です。

Python は「コードは書く回数より読まれる回数のほうがずっと多い」という考えを強く持っています。公式の設計方針(The Zen of Python。対話モードで import this と打つと表示されます)には「Readability counts(読みやすさは大事)」という一文があります。そのため、読むときに目が引っかかる記号をなるべく減らし、英語の文に近い形で書けるようにしてあります。

図は、JS の書き方と Python の書き方の対応表です。

JSPython理由
{ … }: と字下げどうせ字下げはするのだから、それを文法にしてしまう
let / const書かない代入した瞬間に名前ができる
=== / !==== / !=型を勝手に変換しないので、厳密な比較が1種類で足りる
&&・! などand・or・not英単語のほうが読み間違えにくい
true / falseTrue / False先頭が大文字(Python の決まり)
null / undefinedNone「無い」を表すものは1つだけ
` ${x} `f"{x}"引用符の前に f を付けるだけ
// コメント# コメントシェルスクリプトなどと同じ記号

文の終わりの ; も要りません。1行が1つの文です(; で区切って1行に複数書くこともできますが、ふつうはしません)。

これから、この表の1行ずつを「なぜそうなっているのか」まで分解していきます。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 2 / 20
  • 一言でいうと:記号を減らし、字下げと英語で書く
  • { … }
  • : と字下げ
  • ブロックの範囲
  • let / const
  • (書かない)
  • 代入した瞬間に変数ができる
  • === !==
  • == !=
  • 最初から型も見て比べる
  • && || !
  • and or not
  • 英単語で書く
  • true / false
  • True / False
  • 先頭が大文字
  • null / undefined
  • None
  • 「無い」は1つだけ
  • `${x}`
  • f"{x}"
  • 文字列への埋め込み
  • // コメント
  • # コメント
  • 行末までがコメント
  • ひらめき
  • Python は「読みやすさ」を文法で強制する言語。波かっこや && の代わりに、字下げと英単語を使う。

ブロックは波かっこではなく、字下げで決まる

JS と Python のいちばん目立つ違いは、ブロック(if の中身などのまとまり)の範囲の決め方です。

図の左の JS では、光っている行の { から } までが if の中です。JS では、字下げ(行頭の空白)は人間が読みやすくするための飾りにすぎません。字下げを全部消しても、1行にまとめても、同じように動きます。

右の Python には { } がありません。代わりに、光っている if …: の行末にコロン `:` があり、その次の行から1段深く字下げした行が if の中になります。深さを元に戻した else: の行で、if の中身は終わります。

JSPython
ブロックの始まり{行末の : と、次の行からの字下げ
ブロックの終わり}字下げを戻した行
字下げの役割見た目だけ(飾り)文法そのもの

なぜこうしたのでしょうか。JS でも、読みやすいコードを書く人は必ず字下げをします。つまり、{ } と字下げの2つで同じことを二重に表しているわけです。二重だと、ずれることがあります。字下げは if の中に見えるのに、{ } の位置のせいで実は外にある、という読み間違いを生むバグが実際に起こります。

Python は「字下げを文法にする」ことで、この二重をなくしました。見た目の範囲と実際の範囲が食い違うことが、文法上ありえないのです。最初は窮屈に感じますが、エディタが自動で字下げしてくれるので、慣れるとむしろ楽になります。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 3 / 20
  • ブロックは波かっこではなく、字下げで決まる
  • JavaScript(Node.js)
  • Python
  • // tenki.js
  • # tenki.py
  • const city = "東京";
  • city = "東京"
  • let temp = 31;
  • temp = 31
  • if (temp >= 30 && city !== "") {
  • if temp >= 30 and city != "":
  • console.log(`${city}は暑い: ${temp}度`);
  • print(f"{city}は暑い: {temp}度")
  • } else {
  • else:
  • console.log("ふつう");
  • print("ふつう")
  • }
  • { から } までが if の中。字下げを全部消しても動く
  • 行末の : の次の行から、1段深い行が if の中。深さを戻した else: で終わる
  • Python には { } も ; も無い。1行が1文で、ブロックの範囲は字下げの深さで決まる
  • だから「見た目の字下げ」と「実際の範囲」が食い違うことが、文法上ありえない
  • ひらめき
  • JS の字下げは飾りで、範囲は { } が決める。Python は字下げそのものが範囲を決める。

字下げの深さが、そのまま入れ子になる

字下げは入れ子にできます。図のコードは、気温のリスト(第4章で説明します)を1つずつ取り出して表示し、30度以上なら「暑い」も出すプログラムです。

python
temps = [28, 31, 33]
for t in temps:
    print("気温:", t)
    if t >= 30:
        print("暑い")
    print("---")
print("おわり")

黄色の帯が for の中(3〜6行目)、赤い帯が if の中(5行目だけ)です。6行目の print("---") は if より浅いので if の外、でも for よりは深いので for の中です。7行目の print("おわり") は一番浅いので、for が終わってから1回だけ動きます。右上の出力が、実際に python3 で動かした結果です。

字下げの決まりは3つだけです。

決まり内容
コロン :if・elif・else・for・while・def・class・with・try などの行末に付け、次の行から1段深くする
深さ1段はスペース4つが標準。PEP 8(Python 公式のコードの書き方の指針)がそう決めている
混ぜないタブとスペースを混ぜると TabError: inconsistent use of tabs and spaces in indentation になる

深さは「そろっていれば」2つでも8つでも文法上は動きますが、世界中の Python のコードはほぼスペース4つです。VS Code などのエディタは、.py ファイルでは Tab キーを押すとスペース4つを入れるようになっているので、ふだんは気にしなくて大丈夫です。

中身がまだ無いブロックを作りたいときは、何もしない文 `pass` を置きます。JS の {} にあたるものです。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 4 / 20
  • 字下げの深さが、そのまま入れ子になる
  • temps = [28, 31, 33]
  • $ python3 nest.py
  • 気温: 28
  • for t in temps:
  • ---
  • 気温: 31
  • print("気温:", t)
  • for の中(3〜6行目)
  • 暑い
  • ---
  • if t >= 30:
  • 気温: 33
  • print("暑い")
  • if の中(5行目だけ)
  • 暑い
  • ---
  • print("---")
  • おわり
  • print("おわり")
  • 字下げの決まり
  • コロン :
  • if・for・def などの行末に付け、次の行から1段深くする
  • 深さ
  • スペース4つで1段が標準(PEP 8 という公式の書き方の指針)
  • 混ぜない
  • タブとスペースを混ぜると TabError。エディタに任せればまず起きない
  • ひらめき
  • 字下げは「見た目」ではなく文法。深さ4つで1段。戻した行でブロックが閉じる。

字下げがずれると、動く前に止まる

字下げを間違えると、どうなるでしょうか。図の左は if の中身の字下げを忘れた例、右は余計に字下げした例です。どちらも python3 3.13 で実際に動かした出力です。

$ python3 bad1.py
  File "bad1.py", line 2
    print(1)
    ^^^^^
IndentationError: expected an indented block after 'if' statement on line 1
$ python3 bad2.py
  File "bad2.py", line 3
    print(2)
IndentationError: unexpected indent

大事なのは、どちらも1行目すら実行されていないことです。第1章で見たとおり、python3 はファイルを実行する前に、まず全体を読んでバイトコードに変換します。その段階で形が崩れていると分かれば、実行を始めずに止まります。

エラー意味よくある原因
IndentationError: expected an indented block: の後に、字下げした行が1行も無い字下げを忘れた、中身をまだ書いていない(pass を置く)
IndentationError: unexpected indent深くする理由の無いところで深くなったコピペでずれた
IndentationError: unindent does not match any outer indentation level戻した深さが、外側のどの深さとも合わないスペース3つと4つが混ざった
TabErrorタブとスペースが混ざった別のエディタで書いたコードを貼った

エラーには line 2 のように行番号と、^ で位置が出ます。まずその行を見て、上の行と深さを見比べてください。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 5 / 20
  • 字下げがずれると、動く前に止まる
  • 字下げを忘れた
  • 余計に字下げした
  • if True:
  • if True:
  • print(1)
  • print(1)
  • print(2)
  • $ python3 bad1.py
  • File "bad1.py", line 2
  • $ python3 bad2.py
  • print(1)
  • File "bad2.py", line 3
  • IndentationError: expected an
  • print(2)
  • indented block after 'if' statement
  • IndentationError: unexpected indent
  • on line 1
  • Python は実行の前にファイル全体を読んで形を確かめる(第1章)。形が崩れていると、1行目すら動かない
  • エラーの行番号と、^ の位置を見れば、どこの字下げがずれたか分かる
  • ひらめき
  • 字下げの誤りは、1行も実行されないうちに IndentationError で知らされる。

変数:let も const も無い。代入した瞬間に生まれる

JS では、変数を使う前に let か const(古くは var)で宣言します。Python には宣言の言葉がありません。

python
temp = 21      # この瞬間に temp という名前が使えるようになる
temp = 23      # もう一度 = を書けば、別の値になる

名前 = 値 と書いた瞬間に、その名前が使えるようになります。まだ一度も代入していない名前を使うと NameError: name 'temp' is not defined になります。

では、JS の const(再代入禁止)にあたるものは? ありません。 図の右のように、CITY = "大阪" と上書きしてもエラーになりません。

代わりに Python では、全部大文字の名前は「定数なので変えないで」という約束になっています(PEP 8 の決まり)。守るのは言語ではなく、読む人と書く人です。「大人どうしの約束(We are all consenting adults)」と言われる、Python らしい考え方です。

JSPython
変数を作るlet temp = 21;temp = 21
定数const CITY = "東京";(再代入はエラー)CITY = "東京"(大文字は約束。再代入してもエラーにならない)
名前の付け方camelCase(maxTemp)snake_case(max_temp)。PEP 8 の決まり
宣言し忘れ厳格モードでは ReferenceErrorそもそも宣言が無い。未代入の名前を読むと NameError

※第15章で扱う型ヒントを使えば CITY: Final = "東京" と書いて、検査の道具(mypy など)に「再代入したら警告して」と頼むことはできます。ただし実行時には何も止めません。

もう1つ、JS から来た人が驚く違いがあります。let は { } の中だけで使える(ブロックスコープ)のに対し、Python では if や for の中で代入した名前が、外でもそのまま使えます。これは第5章のスコープで詳しく見ます。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 6 / 20
  • 変数:let も const も無い。代入した瞬間に生まれる
  • JavaScript(Node.js)
  • Python
  • let temp = 21;
  • temp = 21
  • const CITY = "東京";
  • CITY = "東京"
  • temp = 23;
  • temp = 23
  • CITY = "大阪";
  • CITY = "大阪"
  • // TypeError: Assignment to
  • # エラーにならない。
  • // constant variable.
  • # 大文字は「変えないで」という約束
  • Python に宣言の言葉は無い。= の左の名前が、その場で使えるようになる
  • 定数を守る仕組みは無く、大文字の名前(CITY)で「変えないで」と読み手に伝えるだけ
  • ひらめき
  • 名前 = 値 と書けば変数ができる。「変えない」は大文字で書くという約束だけ。

型は変数ではなく、値の側にある

Python の変数について、ここで1つ大事な見方を身につけておきます。変数は値を入れる「箱」ではなく、値に付ける「名前の札」だ、という見方です。

図の右側に、21 というオブジェクトがあります。Python では、数も文字列も True も None も、すべてオブジェクト(メモリ上に置かれた1つの物。自分が何の型かを知っている)です。この 21 は「私は int(整数)です」という情報を自分の中に持っています。

x = 21 と書くと、Python は次のことをします。

順番起きること
1右辺の 21 を評価し、int のオブジェクトを用意する
2左辺の x という名前の札を、そのオブジェクトに付ける

type(x) と書くと <class 'int'> と返ってきます。これは「x の型」を聞いているようで、実は「x という札が付いているオブジェクトの型」を聞いています。型を持っているのは札ではなく、オブジェクトの側です。

JS でも考え方は同じで、let x = 21 の x 自体に型はなく、中の値が number です(だから typeof x は値の型を返します)。Python は、それを「すべてがオブジェクト」という形で徹底しています。

この「名前は札、札はオブジェクトに付ける」という見方は、第4章で list を扱うときに、とても大事になります。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 7 / 20
  • 型は変数ではなく、値の側にある
  • 名前(札)
  • オブジェクト(値の実体)
  • x
  • 21
  • 付ける
  • int(整数)
  • x = 21
  • print(type(x))
  • <class 'int'>
  • Python の値はすべて「オブジェクト」。数の 21 も、型(int)を内側に持った1つの物として存在する
  • 変数 x は入れ物ではなく、そのオブジェクトに付けた名前の札にすぎない
  • ひらめき
  • x = 21 は「21 という int のオブジェクトに、x という札を付ける」こと。型を持つのは 21 のほう。

別の値を代入すると、札が付け替わる

続けて x = "晴れ" と書くと、図のように札 x が 21 から離れ、"晴れ" という str(文字列)のオブジェクトに付け替わります。

python
x = 21
print(type(x))   # <class 'int'>
x = "晴れ"
print(type(x))   # <class 'str'>

x の型が int から str に「変わった」ように見えますが、実際には x が別のオブジェクトを指すようになっただけです。21 が "晴れ" に変身したわけではありません。

このように、1つの名前にいろいろな型の値を付けられる性質を動的型付けと呼びます。JS の let と同じです。TypeScript のように「この変数は number だけ」と縛る仕組みは、Python では型ヒント(第15章)と外部の検査の道具で後から足します。

札が1枚も付いていないオブジェクト(図の灰色の 21)は、もう誰からも使えません。Python は各オブジェクトに「何枚の札・参照が付いているか」を数えていて、0 になったものを自動で片付けます(参照カウントとガベージコレクション)。JS と同じく、メモリを自分で解放する必要はありません。

考え方意味
オブジェクト型と中身を持った、メモリ上の1つの物
名前(変数)オブジェクトに付ける札。型は持たない
代入 =札を付ける・付け替える。値のコピーはしない

最後の「代入はコピーをしない」が、第4章の「変更できる入れ物」と組み合わさったときに効いてきます。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 8 / 20
  • 別の値を代入すると、札が付け替わる
  • 名前(札)
  • オブジェクト(値の実体)
  • x = "晴れ"
  • print(type(x))
  • 21
  • 札が1枚も無い物は、あとで自動で片付けられる
  • <class 'str'>
  • int(整数)
  • x
  • 付け替える
  • 晴れ
  • str(文字列)
  • JS の let と同じく、同じ名前に別の型の値を入れられる(動的型付け)
  • ただし、この「名前は札」という考え方は第4章でもう一度、大事な場面で出てくる
  • ひらめき
  • x = "晴れ" で札が str のオブジェクトへ移る。x の型が変わったように見えるのはそのため。

基本の型:int・float・str・bool・None

Python の基本の型は5つです。JS と並べると図の表のようになります。

JSPython例違うところ
number(整数)int21、-3、2**100桁数の上限が無い
number(小数)float21.5、1e-3中身は JS の number と同じ64ビットの浮動小数点数
stringstr"東京"、'東京'' と " はまったく同じ意味
booleanboolTrue、False先頭が大文字
null / undefinedNoneNone「無い」を表すものは None だけ

JS の number は1種類で、整数も小数も同じ型でした。Python は整数(int)と小数(float)を別の型として分けています。21 と書けば int、21.0 や 21.5 と書けば float です。

JS には「まだ値が無い(undefined)」と「わざと空にした(null)」の2つがありますが、Python は None の1つだけです。関数が何も返さなかったときも None になります(第5章)。

文字列には、JS と同じく '…' と "…" のどちらも使えて、違いはありません。中に ' を含めたいときは "…" で囲む、という使い分けだけです。複数行の文字列は """…"""(三連引用符)で書きます。

型を調べるには type(値) を使います(図の下の板)。JS の typeof にあたりますが、type はオブジェクトのクラス(型の設計図・第7章)そのものを返すので、<class 'int'> のように表示されます。

小さな豆知識として、True と False は実は int の仲間で、True + True は 2 になります(公式ドキュメントにも「bool は int のサブタイプ」とあります)。ふだん使うことはありませんが、知っておくと驚かずに済みます。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 9 / 20
  • 基本の型:int・float・str・bool・None
  • JS
  • Python
  • 書き方の例
  • 違うところ
  • number(整数)
  • int
  • 21、-3、2**100
  • 桁数の上限が無い
  • number(小数)
  • float
  • 21.5、1e-3
  • 中身は JS の number と同じ
  • string
  • str
  • "東京"、'東京'
  • ' と " は同じ意味
  • boolean
  • bool
  • True、False
  • 先頭が大文字
  • null / undefined
  • None
  • None
  • 「無い」は None だけ
  • type(21) → <class 'int'> / type(21.5) → <class 'float'> / type(None) → <class 'NoneType'>
  • ひらめき
  • JS の number は int と float に分かれる。true は True、null と undefined は None 1つ。

数:整数と小数が別の型。割り算は2種類

int と float が分かれているので、割り算も2種類あります。図の左は、対話モード(REPL。第1章)で実際に打った結果です。>>> の行が入力、その下が結果です。

演算PythonJSメモ
/7 / 2 → 3.5同じPython の / は、割り切れても必ず float を返す(6 / 2 → 3.0)
//7 // 2 → 3Math.floor(7 / 2)切り捨ての割り算。マイナス方向に切り捨てる(-7 // 2 → -4)
%-7 % 2 → 1-7 % 2 → -1負の数の余りの符号が違う。Python は // と組になるよう決めてある
**2 ** 10 → 1024同じべき乗

int には桁数の上限がありません。2 ** 100 はそのまま31桁の整数になります。JS の number は整数を正確に表せるのが約9000兆(2の53乗)までで、それを超えると BigInt(123n)を使う必要がありますが、Python は int のまま大きくなります。

一方、float は JS の number と同じ仕組みなので、0.1 + 0.2 が 0.30000000000000004 になるのも同じです。お金の計算のように誤差を許せないときは、標準ライブラリの decimal を使います。

文字列を数に変えるには int("21")・float("21.5")、数を文字列にするには str(21) を使います。int("21度") のように数として読めない文字列を渡すと ValueError になります。JS の parseInt("21度") が 21 を返すのとは違い、あいまいなものは受け付けません。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 10 / 20
  • 数:整数と小数が別の型。割り算は2種類
  • >>> 7 / 2
  • 演算
  • Python
  • JS
  • 3.5
  • >>> 7 // 2
  • 3
  • 割り算
  • 7 / 2 → 3.5
  • 7 / 2 → 3.5
  • >>> -7 % 2
  • 1
  • 切り捨て
  • 7 // 2 → 3
  • Math.floor(7/2)
  • >>> 2 ** 100
  • 1267650600228229401496703205376
  • 余り
  • -7 % 2 → 1
  • -7 % 2 → -1
  • >>> 0.1 + 0.2
  • 0.30000000000000004
  • べき乗
  • 2 ** 10
  • 2 ** 10
  • >>> int("21") + 1
  • 22
  • 大きな整数
  • int のまま
  • BigInt(123n)
  • 小数の誤差
  • 同じ
  • 同じ
  • ※ >>> は対話モード(REPL・第1章)の入力の印
  • ひらめき
  • / はいつも小数を返し、// は切り捨て。int はどれだけ大きくしても桁あふれしない。

JS のように、勝手に型を変えない

JS から来た人が Python で最初につまずくのが、図の例です。

python
>>> "気温: " + 21
TypeError: can only concatenate str (not "int") to str

JS なら "気温: " + 21 は "気温: 21" になります。JS は型が合わないとき、「たぶんこういう意味だろう」と暗黙の型変換をして処理を続けるからです。ところが、その推測はときどき外れます。"5" * 2 は数に変えて 10、"5" + 2 は文字列に変えて "52"。同じ "5" なのに、演算子によって変換の向きが逆になります。

Python は、型の合わない演算に出会うと推測せずに止まって、TypeError で知らせます。こういう性質を強い型付けと呼びます。「動的型付け(名前に型が無い)」とは別の話で、Python は「動的」かつ「強い」言語です。

JSPython
"気温: " + 21"気温: 21"TypeError
"5" * 210'55'(文字列を2回くり返す)
"5" + 2"52"TypeError
変えたいときString(21)、Number("5")str(21)、int("5")、float("5")

"5" * 2 が '55' になるのは型変換ではなく、「文字列 × 整数 = くり返し」という決まった演算です("-" * 20 で区切り線が作れて便利です)。

なぜこうするのか。黙って "52" になってしまうと、その値がずっと先で使われたときに初めて変な結果が出て、原因を探すのが大変です。間違いはその場で落ちたほうが、直すのが楽、というのが Python の考え方です。

文字列と数をつなげたいときは、str() で変えるか、次に見る f-string を使います。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 11 / 20
  • JS のように、勝手に型を変えない
  • JavaScript(Node.js)
  • Python
  • "気温: " + 21
  • >>> "気温: " + 21
  • // → "気温: 21"
  • TypeError: can only concatenate
  • "5" * 2
  • str (not "int") to str
  • // → 10(数に変えてから掛ける)
  • >>> "気温: " + str(21)
  • "5" + 2
  • '気温: 21'
  • // → "52"(文字列に変えてつなぐ)
  • >>> "5" * 2
  • '55'(文字列を2回くり返す)
  • >>> int("5") * 2
  • 10
  • JS は型が合わないと「たぶんこうだろう」と変換して続ける。Python は止めて知らせる(強い型付け)
  • 黙って "52" になる不具合より、その場で落ちるほうが原因を探しやすい、という考え方
  • ひらめき
  • "気温: " + 21 は JS なら動き、Python では TypeError。変えるときは str()・int() で自分で変える。

文字列の埋め込みは f-string

JS では、文字列の中に値を埋め込むとき、バッククォートで囲んで ${…} と書きます(テンプレートリテラル)。Python では、引用符の前に `f` を付けて、`{…}` と書きます。これを f-string(フォーマット済み文字列リテラル)と呼びます。

python
city = "東京"
temp = 21.456
print(f"{city}は{temp}度")        # 東京は21.456度

{ } の中には、名前だけでなく式が書けます。そして : の後ろに表示の形(書式指定)を書けるのが、JS のテンプレートリテラルにない便利なところです。図の表は、どれも実際に動かした結果です。

書き方結果意味
f"{temp:.1f}度"21.5度小数1桁に丸めて表示
f"{1234567:,}"1,234,5673桁ごとにカンマ
f"{temp=}"temp=21.456名前と値を一緒に出す。調べもの(デバッグ)に便利
f"{'暑い' if temp >= 30 else 'ふつう'}"ふつう条件の式も書ける

JS で同じことをすると temp.toFixed(1) や n.toLocaleString() を呼ぶことになります。Python は : の後ろの短い書き方で済みます。

f を付け忘れると、"{city}は{temp}度" がそのまま表示されます。エラーにならないので気づきにくい間違いです。{ が出てきたら、先頭に f があるか確かめてください。

古いコードでは "{}は{}度".format(city, temp) や "%sは%d度" % (city, temp) という書き方も見かけます。どれも動きますが、今から書くなら f-string で十分です。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 12 / 20
  • 文字列の埋め込みは f-string
  • JS
  • `${city}は${temp}度`
  • Python
  • f"{city}は{temp}度"
  • 書き方
  • 結果(temp = 21.456)
  • 意味
  • f"{temp:.1f}度"
  • 21.5度
  • : の後ろで表示の形を指定(小数1桁)
  • f"{1234567:,}"
  • 1,234,567
  • 3桁ごとにカンマ
  • f"{temp=}"
  • temp=21.456
  • 名前と値を一緒に出す(調べもの用)
  • f"{'暑い' if temp >= 30 else 'ふつう'}"
  • ふつう
  • 式も書ける
  • ひらめき
  • JS のテンプレートリテラルの代わりに、引用符の前に f を付ける。{ } の中には式が書ける。

=== は無い。Python の == は最初から厳密

JS では「== は使わず === を使え」と教わります。JS の == は、型が違うと片方を変換してから比べるので、1 == "1" や 0 == "" が true になってしまうからです。

Python には === がありません。書くと SyntaxError です。代わりに、`==` が最初から型を変換しません。図の表のとおり、1 == "1" も 0 == "" も False です。前に見た「勝手に型を変えない」という考え方が、比較にもそのまま当てはまっています。

式JSPython
1 == "1"trueFalse
0 == ""trueFalse
1 == 1.0trueTrue(int と float でも、数どうしは値で比べる)
1 === "1"falseSyntaxError
[1, 2] == [1, 2]falseTrue

表の最後の行に注目してください。JS では、配列どうしを === で比べると、中身が同じでも false になります。JS の === は、オブジェクトについては「同じ物(同じ参照)か」を比べるからです。

Python の == は「中身が同じか」を比べます。list、dict、tuple などは、要素を順に比べて全部等しければ True です。第7章で見るように、自分で作ったクラスでも「何をもって等しいとするか」を決められます。

では、Python で「同じ物か」を比べたいときは? それが is です。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 13 / 20
  • === は無い。Python の == は最初から厳密
  • 式
  • JS
  • Python
  • 1 == "1"
  • true(型をそろえてから比べる)
  • False
  • 0 == ""
  • true
  • False
  • 1 == 1.0
  • true
  • True(数どうしは値で比べる)
  • 1 === "1"
  • false
  • SyntaxError(=== は無い)
  • [1, 2] == [1, 2]
  • false(別の配列だから)
  • True(中身が同じだから)
  • JS の == は型を変換してから比べるので、=== を使うのが常識。Python の == は変換をしないので、1つで足りる
  • 最後の行が大事:JS の === は「同じ物か」、Python の == は「中身が同じか」。では「同じ物か」は?
  • ひらめき
  • == は型の違うものを同じと見なさない。さらに list どうしなら「中身」を比べる。

== は中身を、is は「同じ物か」を比べる

図の左のコードを、札とオブジェクトの絵で見てみます。

python
a = [21, 23]
b = [21, 23]
c = a

1行目で list のオブジェクトが1つ作られ、札 a が付きます。2行目では、中身が同じ別の list がもう1つ作られ、札 b が付きます。3行目の c = a は、コピーを作りません。a が付いているのと同じオブジェクトに、札 `c` を付けるだけです(代入は札を付けるだけ、でした)。

式結果理由
a == bTrue中身が同じ
a is bFalse別々のオブジェクト
a is cTrue同じオブジェクトに付いた2枚の札

つまり、JS の ===(オブジェクトについて)にあたるのが Python の is、Python の == は JS には直接あたるものが無い「中身の比較」です。

is を日常で使うのは、ほぼ `x is None` のときだけです。None は Python の中に1つしか存在しないので、「同じ物か」を見れば確実だからです。PEP 8 も、None との比較には == ではなく is / is not を使うように書いています。

逆に、数や文字列の比較に is を使ってはいけません。a is 1000 のような比較は、たまたま True になったりならなかったりします(Python 3.8 以降は警告も出ます)。値の比較は `==`、None の確認は `is` と覚えておけば十分です。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 14 / 20
  • == は中身を、is は「同じ物か」を比べる
  • a = [21, 23]
  • b = [21, 23]
  • a
  • c = a
  • [21, 23]
  • a == b # True
  • a is b # False
  • c
  • list(1つ目)
  • a is c # True
  • c = a はコピーを作らない。
  • 同じ物に2枚目の札を付けるだけ
  • b
  • [21, 23]
  • if x is None: ← None は世界に1つしか無いので is で比べる
  • list(2つ目)
  • ひらめき
  • a is b は、2つの名前が同じオブジェクトに付いているか。None を調べるときは is None と書く。

空っぽは False:[] と {} が偽になる

if の条件には、True / False 以外の値も書けます。そのとき「真と見なすか、偽と見なすか」の決まりが、JS と Python で少し違います。

Python の公式ドキュメントの「真理値判定」の節によると、偽と見なされるのは次のものです。

種類偽になるもの
定数None、False
数のゼロ0、0.0 など
空の入れ物''(空の文字列)、()、[]、{}、set()、range(0)

それ以外は真です。図の表で、JS と違うのは赤い札の3行です。

値JSPython
NaN偽真(bool(float("nan")) は True)
空の配列・list []真偽
空のオブジェクト・dict {}真偽

いちばん効いてくるのは、空の list や dict が偽になることです。JS では「配列が空か」を調べるのに if (items.length > 0) と書きますが、Python ではそのまま if items: と書きます。「中身が1つ以上あれば真」という意味になり、これが Python らしい書き方とされています(PEP 8 も推奨しています)。

python
items = []
if items:
    print("ある")
else:
    print("空")      # → 空

ただし、「None か、空の list か」を区別したいときは if items: では足りません。どちらも偽になるからです。そういうときは if items is None: と明示します。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 15 / 20
  • 空っぽは False:[] と {} が偽になる
  • 値
  • JS
  • Python
  • items = []
  • 0 / 0.0
  • 偽
  • 偽
  • if items:
  • print("ある")
  • "" / ''(空の文字列)
  • 偽
  • 偽
  • else:
  • print("空")
  • # → 空
  • null・undefined / None
  • 偽
  • 偽
  • NaN / float("nan")
  • 偽
  • 真
  • ここが違う
  • JS なら items.length > 0 と書くところ
  • [](空の配列・list)
  • 真
  • 偽
  • ここが違う
  • {}(空のオブジェクト・dict)
  • 真
  • 偽
  • ここが違う
  • "0"・" "(中身のある文字列)
  • 真
  • 真
  • ひらめき
  • Python は「空の入れ物」を偽と見なす。if items: と書けば「1つ以上あるか」の意味になる。

&& || ! は and or not。三項演算子は後ろに if

論理演算は、記号の代わりに英単語で書きます。

JSPythonメモ
a && ba and ba が偽なら a、そうでなければ b を返す
縦棒2本の「または」a or ba が真なら a、そうでなければ b を返す
!anot a必ず True か False を返す
c ? x : yx if c else y条件が真ん中に来る
0 <= t && t < 300 <= t < 30比較をつなげて書ける
a ?? b(無い)a if a is not None else b と書く

and と or が True / False ではなく、どちらかの値そのものを返すのは、JS の &&・|| と同じです。公式ドキュメントにも「or と and は常にどちらかの被演算子を返す」とあります。だから name = input_name or "名無し" のように、既定値を入れる書き方ができます。

三項演算子は、語順が JS と違います。"暑い" if temp >= 30 else "ふつう" は、英語の「暑い、もし30度以上なら。そうでなければ、ふつう」の順です。最初は戸惑いますが、声に出して読むと覚えやすくなります。

比較をつなげる 0 <= t < 30 は、数学の書き方そのままで、0 <= t and t < 30 と同じ意味です。JS で 0 <= t < 30 と書くと、(0 <= t) が true か false になり、それを 30 と比べるのでいつも true になるという有名な落とし穴がありますが、Python では意図どおりに動きます。

JS の ??(null 合体演算子)にあたる演算子は、Python にはありません。図の下の注意のとおり、or は 0 や "" も「偽」として既定値に置き換えてしまうので、「None のときだけ」にしたいなら is None で確かめる式を書きます。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 16 / 20
  • && || ! は and or not。三項演算子は後ろに if
  • JS
  • Python
  • メモ
  • a && b
  • a and b
  • a が偽なら a、そうでなければ b
  • a || b
  • a or b
  • name or "名無し" のように既定値に使う
  • !a
  • not a
  • c ? x : y
  • x if c else y
  • 条件が真ん中に来る
  • 0 <= t && t < 30
  • 0 <= t < 30
  • 比較をつなげて書ける
  • a ?? b
  • (無い)
  • a if a is not None else b と書く
  • ※ or は 0 や "" も「偽」として飛ばす。None のときだけ既定値にしたいなら is None で確かめる
  • ひらめき
  • 記号の代わりに英単語。and / or が「値そのもの」を返すのは JS と同じ。

コメントは #、表示は print

コメントは # から行末までです。JS の /* … */ のような複数行のコメントの記号はありません。複数行にわたるときは、各行の頭に # を付けます。

"""…"""(三連引用符)で囲んだものは、コメントではなく複数行の文字列です。どこにも代入しなければ何もしないので、コメント代わりに見えることがありますが、本来の使いみちは関数やファイルの先頭に置くdocstring(説明文。JS の JSDoc にあたる)です(第5章)。

表示には print を使います。JS の console.log にあたります。

python
print("東京", 31, "度")
print("東京", 31, sep=" / ", end="!\n")
東京 31 度
東京 / 31!
引数意味既定
並べた値何個でも。数でも文字列でもそのまま渡せる―
sep=値と値の間に入れる文字空白1つ
end=最後に付ける文字改行 \n

sep= や end= のように、名前=値 の形で渡す引数をキーワード引数と呼びます。JS にはない仕組みで、第5章で詳しく見ます。

ちなみに print("気温:", 21) のように、print に並べて渡すなら数を str() で変えなくても大丈夫です。print が中で文字列に変えてくれます。TypeError になるのは、自分で + でつなげたときだけです。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 17 / 20
  • コメントは #、表示は print
  • # 1行のコメント。行末に書いてもよい
  • JS
  • Python
  • """
  • 三連引用符は、複数行にまたがる文字列。
  • console.log(a, b)
  • print(a, b)
  • 関数の説明(docstring・第5章)によく使う
  • """
  • // コメント
  • # コメント
  • print("東京", 31, "度")
  • print("東京", 31, sep=" / ", end="!\n")
  • /* 複数行 */
  • (無い。# を並べる)
  • JSDoc /** … */
  • docstring """ … """
  • $ python3 show.py
  • (区切り文字は空白)
  • sep= で変えられる
  • 東京 31 度
  • 東京 / 31!
  • (改行は必ず付く)
  • end= で変えられる
  • ひらめき
  • console.log の代わりに print。並べた値は空白で区切られ、最後に改行が付く。

tenki の最初の1ファイル

ここまでの文法で、本全体で育てていく tenki の最初の版が書けます。天気はまだ手で書いた値です。本物の天気を取ってくるのは、ライブラリを入れる第11章からです。

python
# tenki.py ― 第3章の版
city = "東京"
temp = 31.4
rain = 0  # 降水確率(%)

if temp >= 30:
    feel = "暑い"
elif temp >= 20:
    feel = "ちょうどいい"
else:
    feel = "寒い"

umbrella = "傘が要る" if rain >= 50 else "傘は要らない"
print(f"{city}: {temp:.1f}度 ({feel}) / {umbrella}")
$ python3 tenki.py
東京: 31.4度 (暑い) / 傘は要らない

使った文法を並べます。

行使った文法
city = "東京"宣言なしの代入(str)
temp = 31.4float
rain = 0 # …行末のコメント
if … elif … elseコロンと字下げのブロック。elif は JS の else if(第6章)
feel = "暑い"if の中で代入した名前を、if の外(最後の行)で使っている
… if rain >= 50 else …三項演算子
f"{temp:.1f}"f-string と書式指定

feel を if の中で作り、if の外で使っているところに注目してください。JS で let feel を if の { } の中に書くと、外からは見えません。Python では if はブロックの範囲を作りますが、名前の見える範囲(スコープ)は作りません。これは第5章でもう一度見ます。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 18 / 20
  • tenki の最初の1ファイル
  • # tenki.py ― 第3章の版
  • city = "東京"
  • temp = 31.4
  • rain = 0 # 降水確率(%)
  • $ python3 tenki.py
  • if temp >= 30:
  • 東京: 31.4度 (暑い) / 傘は要らない
  • feel = "暑い"
  • elif temp >= 20:
  • feel = "ちょうどいい"
  • else:
  • elif は JS の else if(第6章)
  • feel = "寒い"
  • 天気を API から取ってくるのは第11章
  • umbrella = "傘が要る" if rain >= 50 else "傘は要らない"
  • print(f"{city}: {temp:.1f}度 ({feel}) / {umbrella}")
  • ひらめき
  • ここまでの文法だけで、tenki の最初の版が書ける。天気はまだ手で書いた値。

よくある間違いと、出るエラー

JS の癖で書いたときに出るエラーは、だいたい決まっています。図の表は、どれも python3 3.13 で実際に出したメッセージです。

書いたもの出るエラー直し方
if temp >= 30(コロン忘れ)SyntaxError: expected ':'行末に : を付ける
else if t > 20:SyntaxError: expected ':'elif t > 20:
i++SyntaxError: invalid syntaxi += 1(++ は無い)
true / nullNameError: name 'true' is not defined. Did you mean: 'True'?True / None
"気温: " + 21TypeError: can only concatenate str (not "int") to strf-string か str(21)
字下げがずれたIndentationError: unexpected indent深さをそろえる
x = None の後に x.upper()AttributeError: 'NoneType' object has no attribute 'upper'先に x is None を確かめる

エラーの種類の名前(SyntaxError、NameError など)を見るだけで、おおよその見当がつきます。

種類意味いつ出るか
SyntaxError / IndentationError文法の形が崩れている実行の前(1行も動かない)
NameErrorその名前が見つからないその行を実行したとき
TypeError型の合わない使い方をしたその行を実行したとき
AttributeErrorそのオブジェクトに、その名前の中身(属性)が無いその行を実行したとき

最近の Python は、Did you mean: 'True'? のように直し方の候補まで出してくれます。エラーの最後の行をよく読むのが、いちばんの近道です。エラー全体(Traceback)の読み方は第18章でまとめます。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 19 / 20
  • よくある間違いと、出るエラー
  • 書いたもの
  • 出るエラー
  • 直し方
  • if temp >= 30
  • SyntaxError: expected ':'
  • 行末に : を付ける
  • else if t > 20:
  • SyntaxError: expected ':'
  • elif t > 20:
  • i++
  • SyntaxError: invalid syntax
  • i += 1
  • true / null
  • NameError: name 'true' is not defined
  • True / None
  • "気温: " + 21
  • TypeError: can only concatenate str …
  • f-string か str(21)
  • 字下げがずれた
  • IndentationError: unexpected indent
  • 深さをそろえる
  • x = None; x.upper()
  • AttributeError: 'NoneType' object …
  • 先に x is None を確かめる
  • ひらめき
  • JS の癖で書くと出るエラーは決まっている。エラーの名前を見れば、何を直せばよいか分かる。

まとめ:記号の違いには、ぜんぶ理由がある

この章で見たことをまとめます。

項目Python では理由
ブロック{ } ではなく、行末の : と字下げ(スペース4つ)見た目と範囲の食い違いをなくす
変数let / const は無い。代入で生まれる名前はオブジェクトに付ける札だから
定数大文字の名前で「変えないで」と約束するだけ大人どうしの約束
型int・float・str・bool・None。型は値の側にあるすべてがオブジェクト
型の変換勝手にしない。str()・int() で自分で変える間違いはその場で落ちたほうが直しやすい
文字列f"{式}"。:.1f などで表示の形を指定―
比較== は中身、is は同じ物か。=== は無い変換しないので == 1つで足りる
真偽0・空の文字列・空の list や dict・None が偽if items: で「中身があるか」と書ける
論理and・or・not、x if 条件 else y、0 <= t < 30英語に近く読める

どの違いも、「読みやすく」「あいまいにしない」という同じ考え方から出ています。

次の第4章では、JS の配列やオブジェクトにあたる、Python のデータの入れ物(list・tuple・dict・set)を見ます。そこで、この章で予告した「名前は札」という見方が本番を迎えます。b = a としたあと b に要素を足すと、なぜ a まで変わるのでしょうか。そして、なぜ文字列では同じことが起きないのでしょうか。

  • JS から来た人の Python 03 ― 基本の文法(JS と並べて)
  • 20 / 20
  • まとめ:記号の違いには、ぜんぶ理由がある
  • 項目
  • Python では
  • ブロック
  • { } ではなく、行末の : と字下げ(スペース4つ)。字下げは文法
  • 変数
  • let / const は無い。代入で生まれ、名前はオブジェクトに付く札
  • 型
  • int・float・str・bool・None。型は値の側にあり、勝手に変換しない
  • 文字列
  • f"{式}" で埋め込む。:.1f などで表示の形を指定できる
  • 比較
  • == は中身(型の違いは別物)、is は同じ物か。=== は無い
  • 真偽
  • 0・空の文字列・空の list や dict・None が偽
  • 論理
  • and・or・not、x if 条件 else y、0 <= t < 30
  • ひらめき
  • 次の第4章:JS の配列とオブジェクトは、Python では何になる?そして「名前は札」の本番。

0 件のコメント

読み込み中…

権利侵害・不適切な内容の連絡: [email protected]