Python入門(2) printと入力、数の計算、文字列

printの改行問題

地味な話であるが、出力 print まわりはどのプログラミング言語でも取り扱いは複雑である(それだけ、印刷物に対する我々の感覚は鋭いわけだ)。 Python2ではprintはprint文であったものが、python3ではprint関数となって取り扱いが首尾一貫した結果、なかなかpython2とpython3とでのすり合わせが難しくなった。

Python2では、print文は原則括弧 ( ) で囲むことはしないのだが、print文の末尾で改行される(次のprint文の先頭文字列は次行の先頭にセットされる)。 Python3でもprint関数の出力(変数や値の並び)を終えると改行される。 つまり、デフォルトではprint文やprint関数を実行すると、表示文字列の末尾に改行文字new line\n が付与されて改行されてしまう。

改行しないprint

Python2ではprint文の最後にコンマ(,)を追加すると改行文字は半角スペースに置き換えられて改行されない。 次のPython2スクリプトの結果を比較して欲しい。 改行されないようにしたとき、Hello と world の間に半角空白が挿入されていることがポイントだ。

# 改行されるprint文
print 'Hello'
print 'world'

# printy文の最後にコンマを追加
print 'Hello',
print 'world'
演習: 上のPython2スクリプトを実行してprint文の改行の有無を確かめなさい。

Python3では、print関数でend = ""を追加すると改行されない。 次のPython3スクリプトの結果を比較して欲しい。 改行されないようにしたとき、Hello と world の間には空文字であることがポイントだ。

# 改行されるprint
print('Hello')
print('world')

# printy内で end = "" を追加
print('Hello', end = "")
print('world')

print関数内でendにセットする文字を変化させてみてほしい。

# printy内で end = "" を追加
print('Hello', end = "")
print('world')
 
# printy内で end = " " を追加
print('Hello', end = "")
print('world')
演習: 上のPython3スクリプトを(Python3環境で)実行してprint結果を検討しなさい。

print並びの区切り文字

以下はPython3のprint関数の説明である。 Python2でPython3のprint関数を使いたい場合には、次のようにスクリプト内で print_function をインポートする。 ただし、そのスクリプト内では printはPython3に準拠して書かねばならない。

from __future__ import print_function
演習: Python2環境で、上のようにしてPython3のprint関数が使えるようにして、以下の説明を確かめなさい。

Python3のprint関数の他のオプションも必要になることがある。 printのオプション sep はprint関数内でカンマ(,)で区切って並べられる表示並びの区切り文字列を指定する。 デフォルトは半角空白であるが、これを変更することができる。

print('Hello', 'world')
 
# printy内で sep を変更
print('Hello', 'world', sep =",")
print('Hello', 'world', sep =", ")
演習: 上のPython3スクリプトを(Python3環境で)実行してprint結果を検討しなさい。

Python3のprint関数のオプションは同時に指定できる。

print('Hello', 'world', sep =",", end = "")
演習: Python3環境でこうしたprint関数のオプションを変更しながら、適切なスクリプトを書いてみなさい。

ユーザーからの入力

Pythonスクリプト実行しながら、ユーザからの入力が利用できると楽しい。 このために用意された関数が raw_input(python2)またはinput(python3)だ。 まず、使い方を知ろう。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# キー入力した文字列を出力
st = raw_input('Input : ')
print('Your input = ', st)

これを実行すると、次のように raw_input( ) 内で指定された文字列が表示されて実行が一旦停止されキーボードからの文字列入力を待ち、それが変数 st に格納され、print文で出力される。 ここでは、入力文字列は Hello とし、次いでEnterを押して文字列入力を終えている。

./raw_input.py               スクリプトの実行開始
Input : Hello              ← 文字列入力
('Your input = ', 'Hello')   実行結果

Python3では、次のように書く。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# キー入力した文字列を出力
st = input('Input : ')
print('Your input = ', st)

キー入力を数字として扱う

Python2の raw_input() またはPython3の input() によるキーボード入力は、上のPython2での実行結果からわかるように、文字列として取り扱われている。 事実、次のようになることからもわかるだろう。

Input : 3.1415              ← 文字列入力
('Your input = ', '3.1415')   実行結果

文字列を整数(integer: 小数点がない)として取り扱うためにはint関数で変換、文字列を浮動小数(float: 小数点がある。実数(real)ともいう)として取り扱うためにはfloat関数で変換する。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# キー入力した2つの数字を足す
n = raw_input('Input an integer : ')
x = raw_input('Input a float : ')
##  for Python3
# n = input('The integer is ')
# x = input('The float is ')

print('Your inputs n, x = ', int(n), float(x))
print('n + y = ', int(n) + float(x))

11,12行目でそれぞれ int や float にキャスとしているが、5,6行目でキー入力を受け取って即キャストした方が後からの手間や間違いを減らすことができるのでベターだ。 つまり次のように書く。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# キー入力した2つの数字を足す
n = int(raw_input('Input an integer : '))
x = float(raw_input('Input a float : '))
##  for Python3
# n = int(input('The integer is '))
# x = float(input('The float is '))

print('Your inputs n, x = ', n, x)
print('n + x = ', n + x)

実行結果は、たとえば次のようになる。

Input an integer : 25
Input a float : 3.1415
('Your input n, x = ', 25, 3.1415)
('n + x = ', 28.1415)

変数の「型変換」を一般にキャスト(cast)という。 int() や float() 以外に、数値(整数や浮動小数)を文字列に変換する関数 str( ) がある。

演習: スクリプト key_input_numbers.py を実行して、整数文字列であるキー入力に浮動小数点文字列を入力するとどうなるかを確かめなさい。
演習(重要): 整数文字列であるべきキー入力に浮動小数点文字列を入力しても、スクリプト内の計算で整数として計算してくれるように、柔軟なスクリプトになるよう key_input_numbers.py を改良し、確かめてみなさい。 (ヒント)int関数は整数文字列を整数に変換するだけでなく、浮動小数を整数に変換することができる(整数キャスト)。int(12.7) や int (-3.2) は 0 に近い整数に値が丸められる。

キーボード入力によってプログラミング結果を確認できることは、次のような同じようなスクリプトよりも明らかに楽しいはずだ。 ここでは、固定的に変数 x には整数 25 が、変数 y には浮動小数点 3.1415 が割り当てられている。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 2つの数を足す
ix = 25
y = 3.1415

print('my setting n, x = ', n, x)
print('n + x = ', n + x)

数の計算

Python Shellを電卓代わりに使うことができる。 割り算 / の取り扱いがPython2とPython3とで若干違っていることに注意しよう。

演算子意味計算式計算結果
+2項の加算a + ba に b を加える
-2項の減算a - ba から b を引く
*2項の乗算a * ba に b を掛ける
/2項の除算a / ba を b で割る
整数同士の整数商12 / 52
//切り捨て除算12.3 // 52.0
%剰余a % ba を b で割った余り
12 % -5-3
-12 % 53
6.5 % 30.5
**べき乗a ** ba の b 乗
2.4 * 37.199999999999999
( )優先計算(4 + 3) * 535

注意:乗算のために記号であるアスタリスク (*) 可変長引数を指定する場合にも使われる。

Python2でキー入力した「数」について、次のようなスクリプトが可能である。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# キー入力した数の計算
n = int(raw_input('Input an integer : '))
y = float(raw_input('Input a float : '))
##  for Python3
# n = int(input('The integer is '))
# y = float(input('The float is '))
# print('Your input n, y = ', n, y)

print n, " + ", y, " => ", n + y
print n, " - ", y, " => ", n - y
print n, " * ", y, " => ", n * y
print n, " / ", y, " => ", n / y
print y, " ** ", n, " => ", y ** y

m = int(raw_input('Input another integer : '))
##  for Python3
# m = int(input('Input another integer : '))

print m, " % ", n, " => ", m % n
演習: 上のスクリプトを実行しなさい。
同様にraw_input関数(Python2)あるいはinput関数を使って、2つの整数 ix, iy や、2つの浮動少数 x, y との四則演算 + - * /(//) を計算するスクリプト compute.py を書いて実行してみなさい。
四則演算の整数同士、浮動小数同士との計算の差異を理解し、数の自在な計算を書くにすることがポイント。

ビット演算

Pythonのビット演算子
代入演算子記法意味
~~aaのビット反転
&a & bビット毎の論理積(aとbの同一桁のビットが両方1のときに1)
|a | bビット毎の論理和(aとbの同一桁のビットのどちらかが1のときに1)
^a *= bビット毎の排他的論理和aとbの同一桁のビットが1と0の時だけ1
<<a << ba を b ビット左シフト
>>a >> ba を b ビット右シフト

代入演算子

Pythonでは CやJavaのように ++ や -- は定義されていないが、次のような代入演算子を使うことができる。
Pythonの代入演算子
代入演算子記法意味
=a = ba に b を代入する
+=a += ba = a + b と同じ
-=a += ba = a - b と同じ
*=a *= ba = a * b と同じ
/=a /= ba = a / b と同じ
//=a //= ba = a // b と同じ
%=a %= ba = a % b と同じ
**=a **= ba = a ** b と同じ
&=a &= ba = a & b と同じ
|=a |= ba = a | b と同じ
^=a *= ba = a * b と同じ
<<=a <<= ba = a << b と同じ
>>=a >>= ba = a >> b と同じ

ここで、

基数変換

整数文字列を整数にキャストする関数 int では、第2引数にその整数を表している基数(radix)を指定して、10進数に変換することができる。

たとえば、0と1からなる文字を使った文字列を基数2の2進数(binary number)であるとみなし、それを10進数(decimal number)に変換できる。 また、0,1,2,3,4,5,6,7からなる文字を使った文字列を基数8の8進数(octal number)であるとみなし、それを10進数に変換できる。 あるいは、0,1,2,3,4,5,6,7,8,9,9,A,B,C,D,F(A〜Fは小文字でもよい)までの文字を使った文字列を基数16の16進数(hexadecimal number)であるとみなし、それを10進数に変換できる。
次の例を丁寧に観察しよう。

>> int("1001", 2)
9
>>> int("123", 8)
83
>>> int("AFF0", 16)
45040

コンピュータの世界では、10進数以外にもしばしば2進数、8進数、16進数がが使われる。 2進数であることを明示するために 0b を左端につけて 0b1001、8進数であることを明示するために 0o を左端につけて 0o123、16進数であることを明示するために 0x を左端につけて 0xAFF0 などと表記する。

実際、スクリプト内で次のよう書くことが可能である。 変数 x には2進数、y には8進数、 z には16進数が割り当てられている。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

x = 0b1001
y = 0o123
z = 0xaff0
print(x, y, z)
print(x + y + z)
演習: 上のスクリプト radix.py を実行しなさい。
演習: キーボードから入力した10進数、2進数、8進数、16進数の整数同士の四則演算を行うスクリプト input_radix.py を書いて実行しなさい。

文字列の連接

文字列についての演算が定義される。 もっとも多用されるのが文字列の連接(concatenattion)で、2つの文字列を並べて新たに文字列とする操作である。 文字列の連接は記号 + で実行できる。

>> print('Hello' +'world')
Helloworld

これは次のように書いても同じことはPython shellですぐに確かめられる。

>>> h = 'Hello'
>>> w = 'world'
>>> print(h + w)
Helloworld

しかし次はうまくいかない。

'Hello' + 21
SyntaxError: invalid syntax
演習: 上のスクリプトが失敗する理由を説明し、実行結果 Hello21 となるように改めなさい。 (ヒント):数を文字列にキャストする。

重要:変数値の上書き

変数 h と w にあり当てた文字列について、h と w を連接 h + w して、その値を再び h に割り当てた時には、以前に格納されていた値は上書き(over write)されてしまうことに注意する。 このことは不都合に思われるかもしれないが、この性質を利用して効率のよく分かりやすいプログラミングが可能になる。

>>> h = 'Hello'
>>> w = 'world'
>>> h = h + w
>>> h
'Helloworld'
>>> w
'world'

文字列の長さ

文字列の長さは関数 len を使って取得できる。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

h = 'Hello'
w = 'world'
print h + w, " has a length ", len(h + w)
演習: 上のスクリプトを実行したり、さまざまに改良してみなさい。
演習: 上の string_length.py で次のようにして日本語文字列に変更してみた。 スクリプトを実行した時に「正しく」表示されるだろうか(python2で書いてみた)。 文字列表示が正常か、文字数のカウント結果が正しいかの2点がポイントである。
#!/usr/bin/env python
# -*- coding: utf-8 -*-

h = '世界は'
w = '広い'
print h + w, " has a length ", len(h + w)

Pythonの文字列単位

Pythonでは,文字列は8ビット単位で格納され,その文字符号化はプラットフォームによって異なる. Pythonで文字単位を処理を行う場合には,Unicode文字列に変換する必要がある. 先の string_length.py をさらに変更し、日本語文字列のまえに u を加えてみた。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

h = u'世界は'
w = u'広い'
print h + w, " has a length ", len(h + w)
演習: 上のスクリプト string_length.p を実行し、先のスクリプト結果と比較検討しなさい。