第2章 リテラル
2-0.Pythonのリテラル
プログラミング言語で、オブジェクトの内容を直接書き込む書式を『リテラル
(直定数,即値 literal)』といいます。
本書ではPythonのリテラルを、『原子リテラル』『集団リテラル』『遅延評価
リテラル』の3種類に分類します。
リファレンスが定義するリテラルに対して、本書ではリテラルの定義がかなり
広くなっています。
これは、構文や式に対して一定の規則の上で理解しやすいように構造化した結
果、その例外的な書式を全てリテラルに含めたためです。
よって、このリテラルの項目は、構文や式の落穂拾い的な項目にもなっていま
す。
尚、この章ではリテラル(記法/書式)について述べるにとどめ、生成されるオ
ブジェクトの詳細については別項にまとめますが、各オブジェクトのの外部表現
については、リテラルと密接な関係にある(リテラルそのままであることが多い)
ので若干触れます。
※外部表現(output representation)
コンソールでオブジェクト名を打ち込んでリターンを押した時に表示される文
字列。またはオブジェクトをrepr関数に渡した時、返される文字列。あるいはオ
ブジェクトの__repr__メソッドおよび__str__メソッドによって返される文字列。
2-1.原子リテラル(atom literal)
2-1-0.原子リテラルと数値
表記したものが、部分分割不可能な1オブジェクトの内容をあらわす時、それ
を原子リテラルといいます。
Pythonの原子リテラルは、数値リテラルしかありません。
※単独の文字専用のリテラルは、Pythonには無いので、文字は全て文字列という
集団リテラル扱いになります。
数値リテラルには、整数リテラル、実数リテラル、そして虚数リテラルがあり
ます。
※有理数(rational number)を扱うオブジェクトもありますが、リテラルはあり
ません。fractionsモジュールのFractionクラスを利用してください。
2-1-0.整数リテラル(integer literal)
整数はデータの基本形です。
初期のPythonでは、整数はクラスインスタンス扱いではありませんでした
また、ごく最近まで、整数には短整数(int)と長整数(long)のリテラルが別々
に存在しました。
現在では、整数は全てintクラスのインスタンスであり、intクラスのリテラル
が唯一の整数リテラルです。
※Python 2までは、long型の長整数の表記には'100L'のように、末尾に'L'ある
いは'l'を添付していました。
整数リテラルには、通常の十進法表記の他に、十六進法や八進法、そして最近
追加された二進法表記などがあります。
以下は全て同じ値となります。
255(外部表現)
0xff 0xFF 0Xff 0XFF
0o377 0O377
0b11111111 0B11111111
通常、二・八・十六進法は、コンピュータの内部表現に用いられますが、
Pythonの整数はあくまで『記数法』ですので、負の数などは以下のように記述し
ます。
-255(外部表現)
-0xff -0xFF -0Xff -0XFF
-0o377 -0O377
-0b11111111 -0B11111111
内部表現などを扱う場合は、集団リテラルの『バイト列』などを使用してくだ
さい。
※なお、二進法、八進法、十六進法表記は、それぞれbin, oct, hex関数で文字
列として表示できます。また、strオブジェクトのformatメソッドを用いると、
数値の整形が可能です。
2-1-1.実数リテラル(real literal)
実数のリテラルは、小数点を加えた形で表記されます。
例えば、255という値は、実数リテラルでは以下のように表現されます。
255.0(外部表現)
小数点以下の0は、いくら続けても良いし、省略してもかまいません。
255.00 255.
また、ピリオドより前の0も省略できます。
.255 ⇒ 0.255
科学演算に使用される、有効数字的な表現も可能です。
2.55e2 2.55E3
これは『真数+常用対数』型の表示であるので、真数がどのような値であって
もつじつまがあっていれば構いません。
以下は全て255.0の実数リテラルとして有効です。
0.255e3 25.5e1 2550e-1 25.5e+1
255e0 255e+0 255e-0
ただし、あくまでリテラル(記述法)であり演算ではないので、対数部分は整数
に限られます。
× 80.638080334293676e0.5(対数部分が整数でないので不可)
実数はfloatオブジェクト(浮動小数点数オブジェクト)で実装されています。
浮動小数点数オブジェクトは、内部では有限ビット数の二進法で実装されてい
るので、桁数が増えると自動的に丸められてしまう他、十進法では表現可能な数
値でも、二進法では表示できない数値などが近似値に置き換わってしまうことも
あります。
よって、実数リテラルは、『文字通り(literal)』の正確な実数が再現される
とは限りません。
※ただし、実数は整数より範囲の大きい数値として、実数と整数の計算結果は実
数になります。
なお、実数オブジェクトの外部表現は、その数値の桁数などの事情によって、
小数点つきの数値('255.0'など)のみで表されるか、あるいは真数+常用対数表
記('2.55e+17'など)のどちらかで表されます。
2-1-2.虚数リテラル(imaginary literal)、複素数リテラル(complex literal)
虚数(imaginary)は、通常数値に'j'を加えて記述します(数学で広く使われて
いるiではないので注意してください)
以下は、数学に於ける255iのリテラルです。
255j 255J 255.j
2.55e2j 2550e-1j
虚数表記は実数表記に'j'あるいは'J'を末尾に加えれば、殆ど通用します。
ただし、内部では全て浮動小数点数で扱っている関係もあり、整数×iの虚数
であっても、整数リテラルのような十進法以外の記数法は使用できません。
ただし、floatオブジェクトの外部表現では、整数値相当であっても整数オブ
ジェクトと区別するために'.0'がつきましたが、桁数が多いものを除き、整数×
iの虚数では'.0'の表示は省略されます(桁数の多いものは、真数+常用対数 型
表記になります)。
なお、一文字の'j'や'J'は、ただの識別子なので、代入されない限り'1j'を意
味しません。
虚数リテラルはcomplexオブジェクト(複素数オブジェクト)を生成します。
複素数オブジェクトについては特にリテラルは存在せず、実数(あるいは整数)
オブジェクトと虚数オブジェクトの加減算によって生成されます(外部表現もそ
れに準じます)
※虚数という言葉は、実数部を含まない『純虚数』だけでなく『実数以外の複素
数』という意味もありますが、本文中では純虚数の意味で用いています。
そのルールは、通常の加減算のルールに従います。
複素数オブジェクトは実数(整数)+虚数の形で表示されますが、実数部分が無
い場合は表示は省略されます。
逆に実数部分がある場合は、虚数部分があろうがなかろうが、'(255+0j)'のよ
うに複素数表示されます。
2-1-3.論理値リテラル(boolean literal)
初期のPythonでは、真偽を表す論理値には、整数の1と0が使用されていまし
た。
現在は、真は'True'、偽は'False'というキーワードが論理値のリテラルとし
て使用されます。
2-2.集団リテラル(collection literal)
2-2-0.集団リテラルとは
Pythonのデータ構造として、リストや辞書などのコレクションがあります。
コレクションとは、0〜複数の「要素(item)」を持つコンテナオブジェクトの
ことです。
組み込みのコレクションに関しては、クラス(コンストラクタ)から生成する
方法、(可変コレクションの場合)要素を追加する方法などがありますが、要素
を直接列挙して記述するリテラルも存在します。
組み込み型のコレクションには、文字列、タプル、リスト、辞書、集合、バイ
ト列、バイト配列などがあります。
2-2-1.文字列(string literal)
2-2-1-0. 基本
Pythonでは、単引用符『'』および二重引用符『"』で囲まれた部分を、文字列
(strオブジェクト)として扱います。
どちらを用いても意味は同じですが、 単引用符で定義された文字列の中では、
文字として二重引用符を使用することができます(逆も可能)
文字列は、必ずコレクションであり、1文字の文字自身をあらわすリテラルは
特にありません。
つまり
'a'
は、『文字オブジェクト』ではなく、長さ1のコレクションである『文字列オブ
ジェクト』と見做されます。
2-2-1-1.エスケープシーケンス(escape sequence)
文字列の中ではバックスラッシュ『\(コード0x5C)』はエスケープ文字として
エスケープシーケンスを入力するために使用されます。
<エスケープシーケンスと意味>
\(改行) 改行の無効化
\\ バックスラッシュそのもの
\' 単引用符(')
\" 二重引用符(")
<ASCIIの制御コード>
\n 改行 / Linefeed (LF) = '\x0A'
\t タブ / Horizontal Tab (TAB) = '\x09'
\a Bell (BEL) = '\x07'
\b Backspace (BS) = '\x07'
\f Formfeed (FF) = '\0C'
\r Carriage Return (CR) = '\x0D'
\v Vertical Tab (VT) = '\x0B'
<文字コードによる指定>
\ooo 八進法による文字コード(ASCII)
('\'+八進法の3桁の数値)
\xhh 十六進法による文字コード(ASCII)
('\x'+十六進法の2桁の数値)
\uxxxx 16ビットキャラクターコード
('\u'+十六進法の4桁の数値)
\Uxxxxxxxx Character with 32-bit
hex value xxxxxxxx
('\U'+十六進法の8桁の数値)
\N{name} Unicodeのデータベースに
収められた名称を入力
ASCIIの制御コードは、端末によっては無効なので、改行'\n'とタブ'\t'以外
は期待すべきではないでしょう。
八進法の文字コードについては、指定された桁数未満の数値であれば対応しま
すが、続けて数値を入れると誤作動するので、頭に0を入れて桁を揃えることを
お勧めします。
例えば、'\n'を入力するなら、'\12'でもいいのですが、'\012'と書いたほう
が安全です。
なぜなら'123\n456'のつもりで'123\12456'と入力すると、'\12'ではなく
'\124'と見なされて'123T56'となってしまいます。
この場合、'123\012456'と書けば、文字どおりの結果が得られます。
十六進法のコードは、要求された桁数が必要になります(×'\xa' ○'\x0a')
UnicodeデータベースのIDを参照して文字列に変換する場合は、以下のように
使います(nameは大文字でも小文字でもかまいません)
<例>
'\N{space}' ⇒ ' '
'\N{SPACE}' ⇒ ' '
'\N{ampersand}' ⇒ '&'
'\N{comma}' ⇒ ','
'\N{colon}' ⇒ ':'
'\N{hyphen}' ⇒ '-'
'\N{left parenthesis}' ⇒ '('
'\N{right square bracket}' ⇒ ']'
'\N{hiragana letter a}' ⇒ 'あ'
なお、ターゲットの文字のUnicodeデータベースののIDは、unicodedataモジュ
ールのname関数を用いて調べることができます。
2-2-1-2.raw文字列(raw string)
『\』自身を文字として認識するには、'\\'と二回続けて書けば良いのですが、
正規表現による検索などで文字列の中に多数の『\』が交じる場合、一々二度づ
つ書くのも大変ですし、見た目も見づらくなります。
raw(生)文字列は、このような場合に効果を発揮します。
raw文字列として記述すると、Pythonはエスケープ記号を『\』という普通の文
字列として扱います。
※raw文字列自体はリテラルの一種なので、それによって記述され、生成された
文字列自体は普通の文字列です。
raw文字列で記述するときは、引用符の前に'r'か'R'を書きます。
r'hello\n' ⇒ 'hello\\n'
ただし、r'\'やr'aaa\'のように、最後に『\』がある(正確には末尾に『\』
が奇数個連続している)とエラーになるので注意してください。
通常の文字列の場合は、末尾の『\』が奇数個並んでいると『\'』が括弧をエ
スケープしてしまいます。
ところがこのルールは、実はraw文字列でも起こります。
つまり、そのままで文字列として成立する文字と記号の並び以外は、raw文字
列としても記述できません。
2-2-1-3.三重引用符(triple quote)による、改行を含む
文字列に限らず、Pythonコードでバックスラッシュで終了する行は、次の行へ
の継続とみなされ、改行は無視されます。
文字列の場合も、最後にバックスラッシュで終了する場合は、その改行が無視
されます。
しかし、三重引用符を用いると、改行をそのまま改行コードとして文字列の中
に読み込むことができます。
三重引用符は、単引用符か二重引用符のどちらかを三回続けて書きます。
'''...''' """..."""
'''aiueo
aiueo''' ⇒ 'aiueo\naiueo'
三重引用符は、同種の(単引用符なら単引用符、二重引用符なら二重引用符)
の『三連続』まで継続するので、二連続までの同種の引用符を文字列に含めるこ
とができます。
'''Say "It's"''' ⇒ 'Say "It\'s"'
2-2-1-4.空文字列リテラル(empty string literal)
空文字列は単引用符か二重引用符の、2連続及び6連続で記述します(外部表
現は『''』)
2-2-2.タプルリテラル(tuple literal)
タプル(tupleオブジェクト、不変リスト)は、基本的にはコンマ(カンマ)演
算子','の適用によって生成されます。
1,2,3 ⇒ (1, 2, 3)
1, ⇒ (1,)
外部表現には括弧がつきますが、タプルがタプルであるためにはコンマが必要
です。
よって、要素1個のタプルを作る場合には、必ずコンマを付与します。
一方、開き丸括弧と閉じ丸括弧の間に、空白と改行以外の要素が無い(あるい
は連続)場合、空タプルのリテラルとなります。
( ) ⇒ ()
他の場合は必須のコンマが、このときだけは必要ありません(書くとエラーに
なります)
(,) ⇒ エラー
タプルの外部表現では(1要素のタプルを除き)必ずコンマの後に空白が一つ
入ります。
2-2-3.リストリテラル(list literal)
リスト(listオブジェクト)は、要素を角括弧で囲うことにより直接記述できま
す(タプルと異なり、一つの要素の場合でも要素の後ろにコンマは要りません)
[1] ⇒ [1]
[1,2,3] ⇒ [1, 2, 3]
タプル同様、開き角括弧と閉じ丸括弧の間に、空白と改行以外の要素が無い場
合、空リストのリテラルとなります。
[ ] ⇒ []
リストの外部表現では(1要素のリストを除き)コンマの後に空白が一つ入り
ます。
2-2-4.辞書リテラル(dictionary literal)
辞書(dictオブジェクト)は、キー(key 不変オブジェクトであればなんでも可
能)と値(value 全てのオブジェクト)のペア(item アイテム)をコンマで区
切ってブレース'{}'の中に記述します。
{'a':1,'b':2,'c':3}
⇒ {'a': 1, 'b': 2, 'c': 3}
空辞書のリテラルは、ブレースのペアで書きます。
{}
辞書の外部表現では(1アイテムの辞書を除き)必ずコンマとコロンの後に空
白が一つ入ります。
2-2-5.集合リテラルと凍結集合リテラル
集合(set)のリテラルは、Python 3になって登場したものであり、歴史的な経
緯で同じブレース括弧を用いる辞書との競合のため、やや変則的な書式になって
います。
要素を全て書き出す場合は、ブレース括弧の中に要素を書き込みます(重複は
自動的に消えます)
{0,1,2,3,2,5,7} ⇒ {0, 1, 2, 3, 5, 7}
ただし、空集合に関しては"{}"が空辞書のリテラルなので、以下のように書き
ます。
set()
これを「リテラルが無い」と評した人もいたようですが、正確に言うならば
「これが空集合のリテラル」なのです。
※個人的にはキーワードを増設して'Phi'(=Φ)とかだと格好良かったかな、
と思いますが
凍結集合(frozenset : 固定/不変集合)は、変更不可能な集合のバージョンで
す。
frozenset((5,8,7,9,6,5)) ⇒ frozenset({8, 9, 5, 6, 7})
※raw文字列でr'...'という表記があるのだから、f{...}でも良かったのでは?
と思うのですが……
凍結空集合のリテラルも、集合とほぼ同じです。
frozenset()
2-2-6.バイト列リテラル、バイト配列リテラル
バイト列(bytes)は、Python 3になって廃止された従来のstrにあたる、バイト
データのシーケンスです。
バイト列のリテラルは特殊で、基本的に文字列の書き方の拡張バージョンにな
ります。
1.文字列のように'か"で囲み、その前に'b'をつける
2.文字コードを指定する時のように、'\xNN'の形式で書き込む(ただし、
xは必ず小文字!)
3.文字コードが、ちょうどASCIIコードの文字のあるナンバーに重なる
場合は、ASCII文字で代用できる
以下に、実際にリテラルと外部表現を書いてみます。
b'\x01\x11\x21\x31\x41\x51\x61\x71' ⇒ b'\x01\x11!1AQaq'
バイト列は不変オブジェクトですが、その可変バージョンがバイト配列
(bytearray)です。
バイト配列コンストラクタはバイト列を引数に取ってバイト配列を生成するの
ですが、リテラルや外部表現も、その形式がそのまま使用されます。
bytearray(b'abc') ⇒ bytearray(b'abc')
バイト列、バイト配列は、文字列のような書式ですが、要素はあくまで整数で
す。
詳細は、オブジェクトの項を参照してください。
2-3.遅延評価リテラル
2-3-0.遅延評価リテラルとは?
遅延評価リテラル(delayed evaluation literal)とは、λ式(lambda
expression)や反復子(イテレータ iterator)式など、その場ですぐには評価され
ない式を記述するリテラルを指します。
これらの扱いは複雑で、lambdaはリファレンスではλ演算子(lambda operator)
と呼ばれ演算子扱いですし、反復子は式扱いです。
本書でこれらをリテラルに分類する理由は以下の通りです。
1.評価内容を具体的に記述する書式(リテラル)である
2.評価結果がオブジェクトとして通用するため、構文扱いはやや不適切。定
義文の一種と見ることもできるが、式の中で扱えるため、応用範囲が異なる
3.式一般(演算子及び関数の適用)のルールからは逸脱しているため、特殊
な書式が多いリテラル扱いが妥当
要約すれば「リテラルとして見るのが一番分かりやすいだろう」ということで
す。
もちろんこれは、筆者独自の考えであり、多く支持された考えではありません。
素直に考えるのなら、λ式は関数定義文の変形、反復子式はfor構文の変形、
そしてリテラルでは扱いませんが、条件付評価式(conditional expression)は
if-else構文の変形、となるでしょう。
しかし、文法の根幹となる構文(定義文や制御文)の例外を増やすことは、
Python文法全体を不必要に複雑化してしまう懸念がありました。
その点リテラルは、文法の中でも特異的な書式がもともと多いので、ここで扱
ったほうが、全体の構造の解釈を大改編するよりも理解しやすいと判断しました。
要するに遅延評価リテラルに属する書式は、かなり例外的なものです。
これを巧く使用すれば、プログラム構造をかなり単純化することが可能となり
ます。
反面、無分別に多用するとPythonが最重要視する『可読性』が損なわれてしま
う可能性が多いにあります。
くれぐれも、扱いは慎重にしましょう。
2-3-1.関数リテラル
lambdaキーワードを使うと、適用することで値を返す関数を、そのまま記述す
る関数リテラル(function literal)が書けます。
lambda x: x + 1
上記は、引数に1を加える関数のリテラル、つまり関数自身となります。
関数を適用させるには、
f(x)
とするので、一度変数に代入して
f = lambda x: x + 1
f(10) ⇒ 11
とすることもできますし、リテラル自身に適用して、
(lambda x: x + 1)(10) ⇒ 11
とすることもできます。
lambdaの一般書式は以下の通りです。
lambda [仮引数[, 仮引数[...]]]: 式
仮引数は、'lambda'と':'の間に書きます。
仮引数は、何個でも(無くても)構いません。
引数リストやキーワード引数の書式は、関数定義と同じですので、関数定義の
章を参照してください。
なお、lambdaキーワードの『演算子』としての優先順位はさほど高くない(と
いうか最低)なので、lambdaの適用範囲は、必要に応じて適宜括弧を使用します。
たとえば、引数を第一要素、10を第二要素とするタプルを返す関数を定義する
際、
lambda x: x, 10
とすると、うまくいきません(関数と10のタプルになってしまいます)
この場合、正しくは
lambda x: (x, 10)
とします。
2-3-2.反復子リテラル
反復子(イテレータ iterator)とは、ある決まった処理を繰り返す(ただし、
大抵結果は異なる)オブジェクトです。
後の関数定義の『継続』の項で示されるジェネレータの式のうち、単純な繰り
返しによるものは、反復子リテラル(iterator literal)として記述可能です。
反復子は、next関数の引数として渡される度に、記述された特定の数値を返し
ます。
簡単な実例を見て見ましょう。
i = (x + 1 for x in [0,1,2])
iは、next(i)を呼び出される毎に、1回目は1を、2回目は2を、3回目は3
を返す反復子の定義です(4回以上呼び出すと、例外が発生します)
先頭の式'x + 1'は、next(i)の返り値のテンプレートになります。
forに続く変数xの中に、inの後にあるリストなどの反復可能オブジェクト
(iteratable object)の要素が順に代入されます。
例えば、1回目はリストの先頭の0がxに代入されて、'x + 1' ⇒ 1 となり、
1が返ります。
そして2回目は1が代入されて……という具合です。
リストなどの反復可能オブジェクトの要素が尽きてしまったら、その後は反復
子は例外'StopIteration'を発生しつづけます。
反復子オブジェクトやジェネレータの詳細は『オブジェクト』の項に譲るとし
て、書式についてさらに説明します。
式の変数として2種類以上の変数に対しforを用いた場合、後ろのforから順に
適用されます。
(x + y for x in (10,20,30)
for y in (1, 2, 3))
の場合、生成される数値は、
11⇒12⇒13⇒21⇒22⇒23⇒31⇒32⇒33
の順に生成されます。
シーケンスに条件を加えてフィルタリングすることもできます。
(x for x in (1,2,3,4,5,6) if x % 2 == 0)
この反復子は、リストの中の偶数のみを生成します(比較演算子'=='や、剰余
演算子'%'については『演算子』の章参照)
条件は、forの数だけ設定できます。
2-3-3.内包表記
一般的に反復子リテラルは、for文と一緒に用いるか、あるいは反復可能オブ
ジェクトを引数とする関数に引き渡されます。
sum(x for x in (1,2,3,4,5)) ⇒ 15
反復子が生成する数値をコレクションにおさめるために特殊な構文糖衣が用意
されています。
※構文糖衣(syntax sugar)とは、同じ内容を簡単に書くための略記法です。反復
子リテラルも構文糖衣の一種と言えます。
反復子が生成する数値をリストにおさめるには、本来は以下のように書きます。
list(x for x in (1,2,3)) ⇒ [1, 2, 3]
構文糖衣を使うと、以下のように書けます。
[x for x in (1,2,3)] ⇒ [1, 2, 3]
このような、ジェネレータによるコレクションの構文糖衣を内包表記
(comprehension)と言います。
集合の内包表記も同じです。
set(x for x in (1,1,2,3)) ⇒ {1, 2, 3}
{x for x in (1,1,2,3)} ⇒ {1, 2, 3}
辞書の内包表記は、少し変わっています。
生成したい辞書が{1:10,2:20,3:30}の場合、
{x:y for x,y in ((1,10)(2,20)(3,30))}
⇒ {1: 10, 2: 20, 3: 30}
と書きます。
もし、xとyを別々のforでくくると、思ったとおりの結果は得られないでしょ
う。
内包表記を使わないと、こうなります。
dict(((x,y) for (x,y) in ((1,10),(2,20),(3,30))))
⇒ {1: 10, 2: 20, 3: 30}
内包表記を使わなければ面倒ですが、内包表記を使ってもあまり便利そうでは
ありません。
実際には、zip関数やrange関数などの組み込み関数と併用することで、内包表
記は威力を発揮します。