3. 形式ばらない Python の紹介
*****************************

以下のサンプルでは、入力と出力はプロンプト (*>>>* や *...*) の有無で区
別します: 例を実際に試す場合は、プロンプトが表示されているときに、サン
プル中のプロンプトから後ろの内容全てを入力します。

このマニュアルにあるサンプルの多くは、対話プロンプトで入力されるもので
もコメントを含んでいます。 Python におけるコメント文は、ハッシュ文字
"#" で始まり、物理行の終わりまで続きます。コメントは行の先頭にも、空白
やコードの後にも書くことができますが、文字列リテラルの内部に置くことは
できません。文字列リテラル中のハッシュ文字はただのハッシュ文字です。コ
メントはコードを明快にするためのものであり、Pythonはコメントを解釈しま
せん。なので、サンプルコードを実際に入力して試して見るときは、コメント
を省いても大丈夫です。

いくつかの例です:

   # これは最初のコメント
   spam = 1  # そしてこれは2つめのコメント
             # ...そして3つめ!
   text = "# これはクォーテーションの間なのでコメントではない。"


3.1. Python を電卓として使う
============================

それでは、簡単な Python コマンドをいくつか試してみましょう。インタプリ
タを起動して、一次プロンプト、 ">>>" が現れるのを待ちます。 (そう長く
はかからないはずです)


3.1.1. 数
---------

インタプリタは、簡単な電卓のように動作します: 式を入力すると、その結果
が表示されます。 式の文法は素直なものです: 演算子 "+" 、 "-" 、 "*" 、
"/" によって算術演算を行うことができ、丸括弧 ("()") をグループ化に使う
ことができます。 例えば:

   >>> 2 + 2
   4
   >>> 50 - 5*6
   20
   >>> (50 - 5*6) / 4
   5.0
   >>> 8 / 5  # 除算は常に浮動小数点数(float)を返す
   1.6

整数 (例えば、 "2" 、 "4" 、 "20") は "int" 型であり、小数部を持つ数 (
例えば、 "5.0" 、 "1.6") は "float" 型です。数値型については後のチュー
トリアルでさらに見ていきます。

除算 ("/") は常に浮動小数点数を返します。 "//" 演算子は *整数除算* を
行い、整数値を返します; 剰余は、"%" で求めます。:

   >>> 17 / 3  # 除算は浮動小数点数を返す
   5.666666666666667
   >>>
   >>> 17 // 3  # 整数除算は小数部を破棄する
   5
   >>> 17 % 3  # % 演算子は剰余を返す
   2
   >>> 5 * 3 + 2  # 切り捨てられた商 * 除数 + 剰余
   17

Python では、冪乗を計算するのに "**" 演算子が使えます [1]:

   >>> 5 ** 2  # 5の2乗
   25
   >>> 2 ** 7  # 2の7乗
   128

等号 ("=") は変数に値を代入するときに使います。代入を行っても、結果は
出力されず、次の入力プロンプトが表示されます。:

   >>> width = 20
   >>> height = 5 * 9
   >>> width * height
   900

変数が "定義" されていない (つまり値が代入されていない) 場合、その変数
を使おうとするとエラーが発生します:

   >>> n  # 未定義の変数にアクセスする
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   NameError: name 'n' is not defined

浮動小数点を完全にサポートしています。演算対象の値(オペランド)に複数の
型が入り混じっている場合、演算子は整数のオペランドを浮動小数点型に変換
します:

   >>> 4 * 3.75 - 1
   14.0

対話モードでは、最後に表示された結果は変数 "_" に代入されます。このこ
とを利用すると、Python を電卓として使うときに、計算を連続して行う作業
が多少楽になります。以下に例を示します:

   >>> tax = 12.5 / 100
   >>> price = 100.50
   >>> price * tax
   12.5625
   >>> price + _
   113.0625
   >>> round(_, 2)
   113.06

この変数には読取りだけを行い、明示的な代入を行ってはいけません --- そ
んなことをすれば、同じ名前で別のローカル変数が生成され、元の特別な動作
をする組み込み変数を覆い隠してしておかしなことになってしまうかもしれま
せん。

"int" と "float" に加え、 Python は "Decimal" や "Fraction" などの他の
数値型もサポートしています。 複素数 も組み込み型としてサポートしており
、 "j" もしくは "J" 接尾辞を使って虚部を示します (例:  "3+5j")。


3.1.2. テキスト
---------------

Python は数値だけでなくテキスト (いわゆる「文字列」である "str" 型によ
って表現されます) を扱うことができます。 "!" のような文字や "rabbit"
のような単語、 "Paris" のような名前、  "Got your back." ような文もすべ
て文字列です。 文字列はシングルクォート ("'...'") またはダブルクォート
(""..."") で囲み、どちらを使っても違いはありません [2] 。

   >>> 'spam eggs'  # シングルクォート
   'spam eggs'
   >>> "Paris rabbit got your back :)! Yay!"  # ダブルクォート
   'Paris rabbit got your back :)! Yay!'
   >>> '1975'  # クォートに囲まれた数字も文字列
   '1975'

クォートの中でクォートを使いたい場合、 "\" を前に付け加えることで「エ
スケープ」をする必要があります。 もしくは、文字列で使用したいクォート
とは別の方のクォートで囲むこともできます。

   >>> 'doesn\'t'  #  \' を使用してシングルクォートをエスケープする
   "doesn't"
   >>> "doesn't"  # または代わりにダブルクォートを使用する
   "doesn't"
   >>> '"Yes," they said.'
   '"Yes," they said.'
   >>> "\"Yes,\" they said."
   '"Yes," they said.'
   >>> '"Isn\'t," they said.'
   '"Isn\'t," they said.'

Python シェルでは、文字列を定義するときと文字列が出力されるときでは見
え方が異なることがあります。 "print()" 関数を使うと、両端のクォートが
なくなり、エスケープされた文字や特殊文字が表示されるため、より読みやす
い形で出力できます。

   >>> s = 'First line.\nSecond line.'  # \n は改行を意味する
   >>> s  # print() を使用しない場合、特殊文字が文字列に含まれる
   'First line.\nSecond line.'
   >>> print(s)  # print() では特殊文字は解釈されるため、\n は改行となる
   First line.
   Second line.

"\" に続く文字を特殊文字として解釈されたくない場合は、最初の引用符の前
に "r" を付けた *raw strings* が使えます:

   >>> print('C:\some\name')  # ここでは \n は改行を意味する!
   C:\some
   ame
   >>> print(r'C:\some\name')  # 引用符の前 r に注目
   C:\some\name

raw文字列には微妙な面があります: raw文字列は奇数個の```` 文字では終了
できません。詳細と解決方法については the FAQ entry を参照してください
。

文字列リテラルは複数行にまたがって書けます。1 つの方法は三連引用符
(""""..."""" や "'''...'''") を使うことです。改行文字は自動的に文字列
に含まれますが、行末に "\" を付けることで含めないようにすることもでき
ます。次の例では最初の改行は含まれません:

   >>> print("""\
   ... Usage: thingy [OPTIONS]
   ...      -h                        Display this usage message
   ...      -H hostname               Hostname to connect to
   ... """)
   Usage: thingy [OPTIONS]
        -h                        Display this usage message
        -H hostname               Hostname to connect to

   >>>

文字列は "+" 演算子で連結させる (くっつけて一つにする) ことができ、"*"
演算子で反復させることができます:

   >>> # 'un' を3回繰り返し、その後に 'ium'
   >>> 3 * 'un' + 'ium'
   'unununium'

連続して並んでいる複数の *文字列リテラル* (つまり、引用符に囲われた文
字列) は、自動的に連結されます。

   >>> 'Py' 'thon'
   'Python'

この機能は、長い文字列を改行したいときにとても役に立ちます:

   >>> text = ('複数の文字列を丸括弧で囲むと'
   ...         '連結される。')
   >>> text
   '複数の文字列を丸括弧で囲むと連結される。'

これは 2 つのリテラルどうしに対してのみ働き、変数や式には働きません:

   >>> prefix = 'Py'
   >>> prefix 'thon'  # 変数と文字列リテラルは連結できない
     File "<stdin>", line 1
       prefix 'thon'
              ^^^^^^
   SyntaxError: invalid syntax
   >>> ('un' * 3) 'ium'
     File "<stdin>", line 1
       ('un' * 3) 'ium'
                  ^^^^^
   SyntaxError: invalid syntax

変数どうしや変数とリテラルを連結したい場合は、"+" を使ってください:

   >>> prefix + 'thon'
   'Python'

文字列は *インデックス* (添字) を指定して文字を取得できます。最初の文
字のインデックスは 0 になります。文字を表す、専用のデータ型は用意され
ていません; 文字とは、単に長さが 1 の文字列です:

   >>> word = 'Python'
   >>> word[0]  # 0番目の文字
   'P'
   >>> word[5]  # 5番目の文字
   'n'

インデックスには、負の値も指定できまます。この場合、右から数えていきま
す:

   >>> word[-1]  # 最後の文字
   'n'
   >>> word[-2]  # 後ろから2番目の文字
   'o'
   >>> word[-6]
   'P'

-0 は 0 と区別できないので、負のインデックスは -1 から始まります。

インデクス表記に加え、 *スライス* もサポートされています。インデクス表
記は個々の文字を取得するのに使いますが、 *スライス* を使うと部分文字列
を取得することができます:

   >>> word[0:2]  # 0番目(含む)から2番目(含めない)までの文字
   'Py'
   >>> word[2:5]  #  2番目(含む)から5番目(含めない)までの文字
   'tho'

スライスのインデックスには、便利なデフォルト値があります; 最初のインデ
ックスを省略すると、0 と見なされます。二番め のインデックスを省略する
と、スライスする文字列のサイズとみなされます。

   >>> word[:2]   # 最初から2番目(含めない)までの文字
   'Py'
   >>> word[4:]   # 4番目(含む)から最後までの文字
   'on'
   >>> word[-2:]  # 後ろから2番目(含む)から最後までの文字
   'on'

開始値は常に含まれ、終了値は常に含まれないことに注意してください。なの
で "s[:i] + s[i:]" は常に "s"  と等しくなります:

   >>> word[:2] + word[2:]
   'Python'
   >>> word[:4] + word[4:]
   'Python'

スライスの使い方をおぼえる良い方法は、インデックスが文字と文字の *あい
だ (between)* を指しており、最初の文字の左端が 0 になっていると考える
ことです。そうすると、 *n* 文字からなる文字列中の最後の文字の右端はイ
ンデックス *n* となります。例えばこうです:

    +---+---+---+---+---+---+
    | P | y | t | h | o | n |
    +---+---+---+---+---+---+
    0   1   2   3   4   5   6
   -6  -5  -4  -3  -2  -1

1行目の数字は文字列の 0 から 6 までのインデックスの位置を示しています;
2行目は対応する負のインデックスを示しています。*i* から *j* までのスラ
イスは、それぞれ *i* と付いた境界から *j* と付いた境界までの全ての文字
から成っています。

正のインデックスの場合、スライスされたシーケンスの長さは、スライスの両
端のインデックスが範囲内にあるかぎり、インデックス間の差になります。例
えば、 "word[1:3]" の長さは 2 になります。

大き過ぎるインデックスを使おうとするとエラーが発生します:

   >>> word[42]  # the word only has 6 characters
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   IndexError: string index out of range

しかし、スライスで範囲外のインデックスを使ったときは、上手く対応して扱
ってくれます:

   >>> word[4:42]
   'on'
   >>> word[42:]
   ''

Python の文字列は変更できません -- つまり *不変* です。従って、文字列
のインデックスで指定したある場所に代入を行うとエラーが発生します:

   >>> word[0] = 'J'
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: 'str' object does not support item assignment
   >>> word[2:] = 'py'
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: 'str' object does not support item assignment

元の文字列と別の文字列が必要な場合は、新しく文字列を作成してください:

   >>> 'J' + word[1:]
   'Jython'
   >>> word[:2] + 'py'
   'Pypy'

組込み関数 "len()" は文字列の長さ (length) を返します:

   >>> s = 'supercalifragilisticexpialidocious'
   >>> len(s)
   34

参考:

  テキストシーケンス型 --- str
     文字列は代表的な *シーケンス型* で、シーケンス型でサポートされて
     いる共通の操作をサポートしています。

  文字列メソッド
     文字列は、基本的な変換や検索を行うための数多くのメソッドをサポー
     トしています。

  f-strings
     式の埋め込みをサポートした文字列リテラル

  書式指定文字列の文法
     "str.format()" を使った文字列のフォーマットについての情報がありま
     す。

  printf 形式の文字列書式化
     文字列が "%" 演算子の左オペランドである場合に呼び出される古いフォ
     ーマット操作について、詳しく記述されています。


3.1.3. リスト型 (list)
----------------------

Pythonは多くの *複合 (compound)* データ型を備えており、複数の値をまと
めるのに使われます。最も汎用性が高いのは *リスト (list)* で、コンマ区
切りの値 (要素) の並びを角括弧で囲んだものとして書き表されます。リスト
は異なる型の要素を含むこともありますが、通常は同じ型の要素のみを持ちま
す。

   >>> squares = [1, 4, 9, 16, 25]
   >>> squares
   [1, 4, 9, 16, 25]

文字列 (や他の全ての組み込みの *シーケンス* 型) のように、リストはイン
デックスやスライスができます:

   >>> squares[0]  # インデックス指定は要素を返す
   1
   >>> squares[-1]
   25
   >>> squares[-3:]  # スライスは新しいリストを返す
   [9, 16, 25]

リストは、リストの連結などもサポートしています:

   >>> squares + [36, 49, 64, 81, 100]
   [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

*不変* な文字列とは違って、リストは *可変* 型ですので、要素を入れ替え
られます:

   >>> cubes = [1, 8, 27, 65, 125]  # 何かがおかしい
   >>> 4 ** 3  # 4の3乗は65ではなく64!
   64
   >>> cubes[3] = 64  # 誤った値を置き換える
   >>> cubes
   [1, 8, 27, 64, 125]

"list.append()" *メソッド* を使って、リストの末尾に新しい要素を追加で
きます (メソッドについては後で詳しく見ていきます):

   >>> cubes.append(216)  # 6の3乗を追加
   >>> cubes.append(7 ** 3)  # 7の3乗を追加
   >>> cubes
   [1, 8, 27, 64, 125, 216, 343]

単純な代入ではPythonは決してデータをコピーしません。リストを変数に代入
すると、その変数は *既存のリスト* を参照します。ある変数を通してリスト
に任意の変更を行うと、そのリストを参照したすべての他の変数を通して確認
できます。:

   >>> rgb = ["Red", "Green", "Blue"]
   >>> rgba = rgb
   >>> id(rgb) == id(rgba)  # 同じオブジェクトを参照している
   True
   >>> rgba.append("Alph")
   >>> rgb
   ["Red", "Green", "Blue", "Alph"]

全てのスライス操作は、指定された要素を含む新しいリストを返します。例え
ば、次のスライスは、リストの 浅いコピー を返します。:

   >>> correct_rgba = rgba[:]
   >>> correct_rgba[-1] = "Alpha"
   >>> correct_rgba
   ["Red", "Green", "Blue", "Alpha"]
   >>> rgba
   ["Red", "Green", "Blue", "Alph"]

スライスには、代入もできます。スライスの代入で、リストのサイズを変更し
たり、全てを削除したりもできます:

   >>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
   >>> letters
   ['a', 'b', 'c', 'd', 'e', 'f', 'g']
   >>> # 一部の値を置き換える
   >>> letters[2:5] = ['C', 'D', 'E']
   >>> letters
   ['a', 'b', 'C', 'D', 'E', 'f', 'g']
   >>> # 一部の値を削除する
   >>> letters[2:5] = []
   >>> letters
   ['a', 'b', 'f', 'g']
   >>> # 要素全体を空のリストに置き換えてリストをクリアする
   >>> letters[:] = []
   >>> letters
   []

組込み関数 "len()" はリストにも使えます:

   >>> letters = ['a', 'b', 'c', 'd']
   >>> len(letters)
   4

リストを入れ子 (ほかのリストを含むリストを造る) にできます。例えば:

   >>> a = ['a', 'b', 'c']
   >>> n = [1, 2, 3]
   >>> x = [a, n]
   >>> x
   [['a', 'b', 'c'], [1, 2, 3]]
   >>> x[0]
   ['a', 'b', 'c']
   >>> x[0][1]
   'b'


3.2. プログラミングへの第一歩
=============================

もちろん、2 たす 2 よりももっと複雑な課題にも Python を使えます。 例え
ば、Fibonacci series の先頭の部分列は次のように書けます:

   >>> # フィボナッチ数列:
   >>> # 2つの要素の和で次の値を定義する
   >>> a, b = 0, 1
   >>> while a < 10:
   ...     print(a)
   ...     a, b = b, a+b
   ...
   0
   1
   1
   2
   3
   5
   8

上の例では、いくつか新しい機能を使用しています。

* 最初の行には *複数同時の代入 (multiple assignment)* が入っています:
  変数 "a" と "b" は、それぞれ同時に新しい値 0 と 1 になっています。こ
  の代入は、最後の行でも使われています。代入文では、まず右辺の式がすべ
  て評価され、次に代入が行われます。右辺の式は、左から右へと順番に評価
  されます。

* "while" は、条件 (ここでは `` a < 10``) が真である限り実行を繰り返し
  (ループし) ます。Python では、C 言語と同様に、ゼロでない整数値は真と
  なり、ゼロは偽です。条件式には、文字列値やリスト値なども使えます。そ
  れ以外のシーケンスも、条件式として使用できます。長さが 1 以上のシー
  ケンスは真で、空のシーケンスは偽になります。サンプルで使われている条
  件テストはシンプルな比較です。標準的な比較演算子は C 言語と同様です:
  すなわち、 "<" (より小さい)、 ">" (より大きい)、 "==" (等しい)、
  "<=" (より小さいか等しい)、 ">=" (より大きいか等しい)、および "!=" (
  等しくない)、です。

* ループの *本体 (body)* は、 *インデント (indent, 字下げ)*  されてい
  ます: インデントは Python において、実行文をグループにまとめる方法で
  す。対話的プロンプトでは、インデントされた各行を入力するにはタブや (
  複数個の) スペースを使わなければなりません。実用的には、もっと複雑な
  処理を入力する場合はテキストエディタを使うことになるでしょう。 ほと
  んどのテキストエディタは、自動インデント機能を持っています。複合文を
  対話的に入力するときには、入力完了のしるしとして最後に空行を入力しま
  す。これは、パーザはどれが最後の行を入力なのか、判断できないためです
  。基本的なブロック内では、全ての行は同じだけインデントされていなけれ
  ばならないので注意してください。

* "print()" 関数は、与えられた引数の値を書き出します。これは (前に電卓
  の例でやったような) 単に出力したい式を書くのとは、複数の引数や浮動小
  数点量や文字列に対する扱い方が違います。"print()" 関数では、文字列は
  引用符無しで出力され、要素の間に空白が挿入されて、このように出力の書
  式が整えられます:

     >>> i = 256*256
     >>> print('The value of i is', i)
     The value of i is 65536

  キーワード引数 *end* を使うと、出力の末尾に改行文字を出力しないよう
  にしたり、別の文字列を末尾に出力したりできます:

     >>> a, b = 0, 1
     >>> while a < 1000:
     ...     print(a, end=',')
     ...     a, b = b, a+b
     ...
     0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,

-[ 脚注 ]-

[1] "**" は "-" より優先順位が高いので、"-3**2" は "-(3**2)" と解釈さ
    れ、計算結果は "-9" になります。これを避けて "9" を得たければ、
    "(-3)**2" と書きます。

[2] 他の言語と違って、"\n" のような特殊文字は、単引用符 ("'...'") と二
    重引用符 (""..."") で同じ意味を持ちます。両者の唯一の違いは、単引
    用符で囲われた箇所では """ をエスケープする必要がない (ただし "\'"
    はエスケープする必要がある) ことで、逆もまた同様です。
