2012/12/06

文系のための「文字列型」(2)

データ型」というのは、コンピュータを使う上で最も基礎的な知識の一つ
それにも関わらず、初学者には理解しにくく、本を読んでも理解し難い。
最も良い方法は、実際にプログラムを書いてみること

このブログの読者の中には、強い抵抗を感じる人も少ないかもしれないが、
プログラミングは、意外にも文系向けの技能。論理的思考ができれば誰でも書ける。
プログラマを目指す必要は無いが、少し書ければ、雑務はかなり減る

別の仕事が増えても責任を取ることはできないが...。

とは言うものの、このブログの目的は、プログラムの話では無いので、
プログラムの書き方を知らない人のことを考えて可能な限り平易に書くように努める。
比較的簡単なプログラミング言語にPythonというものがある。以下ではこれを用いる。

公式サイトは、http://www.python.org/ 。ここで、ダウンロードできる。
もちろん、無償で入手できる。注意すべきはバージョン
インストールするべきは、「2.x」。このブログ執筆時には「2.7」

とにかく「Python 2.7 」をインストール。

「2.x」と「3.x」はかなり違う。間違えると以下の処理ができないかもしれない。
この二つのバージョン、現在でも、同時並行で使われている。
「3.x」の方が最新バージョン、という訳では無いので注意。

Python のインストール方法は、探せば丁寧な説明は多く存在するはず。
Google検索で「Python2.7 インストール方法」などと検索するのが良い。
私が説明するよりも解りやすい説明をしている人がいるはず。

さて、ここから先は、インストールをしていることを前提に話を進める。
もちろん、インストールして無くても良いのだが、
折角の機会でもあるし、まだの人はインストールすることを進める。

以上の準備が完了したら、Python を起動する。
Windows の人は、IDLE(Python GUI) というプログラムをし、
MacUbuntu の人は、Terminal(端末)上で Python と入力して実行する。

とりあえず、画面上に「>>>」という記号が表示してあって、
その横で「|」が点滅している状態であれば大丈夫。
この状態はコマンドの待機状態。コンピュータに命令できる状態。

この画面を「コンソール画面」と呼ぶ。
では、Pythonにおける文字列型」の話を続けることにしよう...。

PostgreSQL文字列型Python文字列型は、当然ながら異なるのであるが、
データ型」を理解するには、様々な環境下のデータ型を理解しておいた方が良い
なお、データ型の定義は、PostgreSQL の方が「厳密」Pythonはかなり「甘い」

PostgreSQLでは4種類の文字列型が存在したが、Python では1種類のみ
Python の文字数限界は、半角英数の場合で「1,073,741,824」文字まで格納でき、
日本語など全角文字の場合では「536,870,912」文字まで格納できる。

このような「性能上」の違いはあるが、基本的な処理の仕組みは同じ
もちろん、文法上の違いはあるが、仕組みを理解できれば今は良い。
Python から PostgreSQL を直接的に操作できるのだから、両方知っておいた方が良い。

さてさて、今回は、初っ端から話が脱線しっぱなしである。話を元に戻そう。
今回の話では、「文字列型基礎的な性質と簡単な演算について理解する。
実は、数値と同じように「文字列型」にも様々な演算が存在している。

とりえあえず、練習から。コンソールに以下の3行をコピーし、
深く深呼吸してから、Pythonコンソール画面に貼り付ける。
コピー&ペーストの作業は、マウス操作で行った方が良い

"Hello"
'Hello'
Hello

すると、以下のような出力が得られるハズ。
何も恐れる必要は無い。別にパソコンが壊れる訳ではない。
日本語のメッセージに置き換わっているかもしれないが同じ内容。

>>> "Hello"
'Hello'
>>> 'Hello'
'Hello'
>>> Hello
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'Hello' is not defined

最初の二行は実行した行の下に 'Hello' というのが表示され、
最後の一つには、何やら、怪しげなメッセージが表示されている。
落ち着いて最後の三行を見てみる。

一行目は、このメッセージの直前の処理から何かのエラーが帰ってきたことを示す。
二行目は、このメッセージが直前の処理の何行目でエラーが発生していたことを示す。
三行目は、このメッセージが伝えているエラーの種類を示している。

NameError: name 'Hello' is not defined

要するに「ネームエラー(Name Error)」というのが出ている。
では、「'Hello' という名前は定義されていません」どういう意味か?
実は、「"」あるいは「'」で囲まれていない文字列は「変数」として認識される。

つまり、プログラム上では、「"」あるいは「'」で囲まれている部分が、
「文字列」として扱われているのである。コンピュータ上では非常に重要な記号の一つ。
ちなみに、現段階では「"」と「'」は、どちらを用いても良い。使い分けはいずれ。

さて、この表記方法、Python に限ったことでは無い
なんと、あのエクセルでも同じ。エクセルにID番号として「12-12-01のようなものを入れると、
勝手に「2012年12月1日」というように日付に変換されたことは無いだろうか?

これは、エクセル入力されたデータから自動的にデータ型を推測
どうやら、このデータは日付型らしい」という判断をした結果である。
この問題に頭を抱えている人を見かけることは少なくない。

実は、この問題の回避する手段は非常に簡単である。
'12-12-01」のように、最初に「クォーテーション」を付けて入力すれば良い。
すると、文字列と認識され、実際には「'12-12-01'として扱われる。

さて、このことを確認できたら、次に「文字列型」の四則演算から実験してみる。
何も考え無くても良いので、以下の4行をコピーして、コンソール画面に貼り付ける。

"Hello" + "World"
"Hello" - "World"
"Hello" * "World"
"Hello" / "World"

すると、以下のような出力が得られる。エラーも出ている。

>>> "Hello" + "World"
'HelloWorld'
>>> "Hello" - "World"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'str' and 'str'
>>> "Hello" * "World"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'str'
>>> "Hello" / "World"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for /: 'str' and 'str'

さて、コピーした4行というのは、"Hello" "World"演算である。
要するに、足し算引き算掛け算割り算の3つの計算を一処理ずつ実行している。
さて、この出力を見て気になるのはエラーの部分

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'str' and 'str'

最初の二行はさっきのエラーと同じ。最後のメッセージ行のみが重要となる。
ここで「str」とは、「string」の略で、Pythonの「文字列型を表すので、
文字列 」と「文字列」の計算において、対応していない演算(記号)が使われたのがエラーの原因。

さて、ここでクイズ。上記4つの処理の中で、唯一このエラーが発生していないのはどれか?
4行分をコピーして実行したのであるが、1処理ずつ実行していることも重要。

>>> "Hello" + "World"
'HelloWorld'

これが答え。エラーを示す三行のエラーメッセージの代わりに、
"HelloWorld" という文字列が表示されている。
以上のことから、文字列は、足し算することができることが解る。

前回の話でも解説したが、「文字列」というのは「文字」の配列である。
つまり、"Hello" という5文字の配列と、 "World"という5文字の配列を足すことができる。
その結果が "HelloWorld"である。このように考えると他の演算が出来ないことも納得できる。

さて、では、以下のような演算は可能であろうか?同様にコピペ。

"Hello" - 4
"Hello" * 4
"Hello" / 4

この演算結果は以下の通り。

>>> "Hello" - 4
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'str' and 'int'
>>> "Hello" * 4
'HelloHelloHelloHello'
>>> "Hello" / 4
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for /: 'str' and 'int'

先程と同様に、この中で一つだけエラーが出ていない命令がある。どれか?
答えは、「"Hello" * 4」の計算。これは、"Hello"という配列が4つという意味。
したがって、'HelloHelloHelloHello' という結果が表示されているのである。

さて、ここでも、エラーを確認してみる。見るべき部分は三つ目の行。
今度は「int」というのが出てきている。これは「整数値型」を意味する。
つまり、文字列と整数値の演算において対応していない演算が行われたことを意味する。

以上のことから、文字列同士の演算は、「足し算」のみが可能であり、
また、文字列と整数値の演算は、「掛け算」のみが可能である。

さて、これで「メデタシ、メデタシ」とはいかない。
実は、文字列と整数値の足し算をまだ実験していない。
この処理、ちょっと、変わった結果になるからである。

"Hello" + 4

というのを実行してみると、以下のようなエラーが出る。

TypeError: cannot concatenate 'str' and 'int' objects

よく見ると、エラーメッセージの内容が先ほどと異なる。
文字列と整数値をくっつけることができません」と言っている。
つまり、演算としては存在するが、整数型を文字列に足すことはできないのである。

そうそう。同じ「」であっても「数値」と「数字」は異なるのであった。
では、プログラミング上で文字列を認識するには、どうすれば良かったのか?
"」あるいは「'」で囲めば良かった。ではやってみる。

"Hello" + "4"

これを実行すると以下のようになる。

>>> "Hello" + "4"
'Hello4'

すると、"Hello" という5文字の配列と"4"という1文字の配列の足し算となり、
この二つをくっつけた文字列として'Hello4'が表示されるのである。
このようにして、文字列を結合することができるのである。

別の考え方もできる。先程は、文字列としての「数」を表すという考え方であったが、
整数型を文字列型に変換するという考え方もできるハズ。
このようなデータ型の変換のことを「キャスト」と呼ぶ。

"Hello" + str(4)

このようにすると、4という数値は、strという文字列型に変換される。

>>> "Hello" + str(4)
'Hello4'

もちろん、結果は先程と同じ'Hello4'である。
なるほど、段々と状況が読めてきた。では、最後に、以下の演算を実験してみる。
以下の3つの計算、実行前に計算結果を予測できるだろいうか?

256 + 256
"256" + "256"
str(128) * 3

では、答え合わせ。実行してみると以下の通りになる。

>>> 256 + 256
512
>>> "256" + "256"
'256256'
>>> str(128) * 3
'128128128'

さて、予想通りの結果になったであろうか?

コンピュータ上では、数値と数字は異なるということと、
文字列の足し算と掛け算が配列に対して行われているということ、
この二つのことが理解できていれば、簡単に予測できたことであろう。

0 件のコメント:

コメントを投稿