Java/Python 導入ガイド《3》リテラル表現としての意義
Java プログラマーのための Python 導入ガイド〈初級/入門編〉《Jython2.5.0》
《3》リテラル表現としての意義
》作業中です《 2006年6月28日 (水)
リテラル表現としての意義
Python では、コレクションを生成するのに便利な「リテラル表現」が可能です。すると、数/文字列などの「リテラル表記」と同様に、多彩な表現が可能となります。
>>> 3,type(3) (3,) >>> "ABC",type("ABC") ('ABC', ) >>> 3+4j,type(3+4j) ((3+4j), )
数/文字列に限らず、任意のオブジェクトの源泉となるのが「リテラル表記」です。リテラル表記による「文字どおりの literal」式を評価するだけで、コンストラクター/メソッドを使わずに、任意のオブジェクトが得られます。このように、リテラル表記が充実していると、コードをより簡潔に表現できます。
■ リテラルはただの定数ではない
Python では、括弧 [] そのものが、オブジェクトを生成する「リテラル表現」と見なせます。つまり「文字どおりの literal」式を評価するだけで得られる「オブジェクトの源泉となる表現」をプログラマーに提供します。
>>>
空文字列をリテラル表記 "" で表現できるように、空リストを表現する括弧 [] が、オブジェクトの源泉となる「リテラル表現」となります。
>>> len(""),len([]) (0, 0)
空文字列の長さ/空リストの要素数は、ともに 0 となります。
>>> bool(""),bool([]) (False, False)
空文字列/空リストは、ともに False と等価です。そのため、if/while などに続く条件式にも指定できます。
数/文字列の場合には、リテラル表記を使って直に情報(データ)を記述できます。リストの場合には、リテラル表現として間接的に情報が得られる式(それを評価すると任意のオブジェクトが得られるもの)を記述します。すると、次のように、
>>> 3,"ABC",[3+4,len("ABC"),"ABC".lower(),True,None] (3, 'ABC', [7, 3, 'abc', True, None])
リテラル表現としての、リストの括弧 [] の中には、
- 演算子 3+4
- 関数 len("ABC")
- メソッド "ABC".lower()
などを含む、任意の式を自由に混在できます。また、他の first-class object と同様に、リストを関数の引数/リターン値にも指定できます。
>>> map(str,[3+4,len("ABC"),"ABC".lower(),True,None]) ['7', '3', 'abc', 'True', 'None'] >>> map(id,[3+4,len("ABC"),"ABC".lower(),True,None]) [25180480, 25180528, 18775104, 3118816, 3156640]
ここでは、組み込み関数 map の実引数に、リテラル表現としてのリストを指定しています。リスト内の各要素に対して、最初の例ではその文字列表現 str が、次の例ではその識別情報 id が得られます。また、他の first-class object と同様に、任意の制御構造 if/for/while との組み合わせも自由です。
>>> if [3+4,len("ABC"),"ABC".lower(),True,None]: ... print "not empty" ... else: ... print "empty" not empty >>> for e in [3+4,len("ABC"),"ABC".lower(),True,None]: ... print hex(id(e)),":",repr(e) ... else: ... print "good luck" 0x1803940 : 7 0x1803970 : 3 0x11c6fa0 : 'abc' 0x2f96e0 : True 0x302aa0 : None good luck >>> while []: ... print "forever" ... else: ... print "the end" the end
■ 純粋な OOP の世界では
ここで注目して欲しいのは、整数/文字列などにも、オブジェクトの識別情報が与えられていることです。純粋な OOP の世界では、すべてが first-class object であり、平等の権利を持つ存在(一人前のオブジェクト)として扱われます。Java の世界では、組み込み型/true/false/null などは、オブジェクトと平等の権利を持たないので、それを補うための支援(ラッパー/ボクシングなど)が必要になります。
純粋な OOP の世界では「リテラル」はただの定数ではありません。オブジェクトの源泉を提供する「定式化された表現」となります。
《付記》Smalltalk では、より多彩なリテラル表現が可能です。たとえば、アルゴリズム定数などの記述も容易です。Python における、今後の課題のひとつです。《ひよ子》
《リストの内包表記》
Python では、内包を使ったリストの表現が可能です。それを説明する前に、数学の授業を思い出してください。集合を表現するには、2つの方法(外延/内包)がありました。たとえば、正の偶数を含む集合 S を表現するのに、外延では、次のように
S = { 2, 4, ... }括弧内に要素を列挙します。内包では、次のように
S = { 2n | n ∈ N } N は自然数の集合要素を列挙するのではなく、{ 要素を表現する数式 | 定義 } という形式で表現します。リストの内包は、これとよく似ています。
>>> # {e | e in "ABC"} >>> [e for e in "ABC"] ['A', 'B', 'C']括弧に続く式 e は、先の「要素を表現する数式」に対応して、リストの各要素を表現する式です。その後には、for に続く変数 e の源泉が文字列 "ABC" にあることを明記します。すると、文字(長さが1の文字列)を要素とするリストが得られます。
>>> # {e.lower() | e in "ABC"} >>> [e.lower() for e in "ABC"] ['a', 'b', 'c']括弧に続く式 e.lower() は、リストの各要素を表現する式です。メソッド lower を適用すると、小文字を要素とするリストが得られます。
《付記》VDM++ では、内包に限らず、多彩な表現が可能です。その点ではむしろ、OOP 言語のほうが後塵を拝しているとも言えます。Ruby/Python における、今後の課題のひとつです。《ひよ子》
==================================
森こねこ 著 ◆ 監修:小泉ひよ子とタマゴ倶楽部