初めてのPython(5章)

オブジェクトの操作には式を使う。
式はオブジェクトと演算子から構成され、オブジェクト毎に使える演算子が決まっていて、同じ演算子でもオブジェクトが違えば意味が異なる(ポリモーフィズム)。
これは、オブジェクト毎に定義が異なっているからで、オーバーロード*1によって実現されている。

変数を使う上で最低限気をつけることは4つ

  1. 値が代入された時点で作成される
  2. 式の中で使うと、演算時に代入した値が使われる
  3. 値を代入していない変数を使うとエラー
  4. 値を代入しないで、宣言だけするとエラー

割り算の演算子は2つある(バージョン3.0では変わるみたい)

また、インタプリタ内で循環小数を表示する時は、print文の有無で表示が異なるので注意が必要。

/演算子と//演算子

式中で型が混在している場合は、最も「複雑」な型にそろえた上で演算が行われる
/演算子と//演算値の違いは出力時の小数点の扱い

演算子 小数点以下
/ 小数点以下も出力
// 小数点以下を切り捨てて表示

整数同士の割り算や//演算子による割り算では切り捨てが行われるので、負数に対する演算では正数とは結果が異なる。

[kobakoba0723@fedora13-intel64 ~]$ python
Python 2.6.4 (r264:75706, Apr  1 2010, 02:55:51) 
[GCC 4.4.3 20100226 (Red Hat 4.4.3-8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> int_a = 5
>>> int_b = 2
>>> float_a = 5.00
>>> float_b = 2.00
>>> (int_a / int_b), (int_a / float_b), (float_a / int_b), (float_a / float_b)
(2, 2.5, 2.5, 2.5)
>>> (-int_a / int_b), (-int_a / float_b), (-float_a / int_b), (-float_a / float_b)
(-3, -2.5, -2.5, -2.5)
>>> (int_a // int_b), (int_a // float_b), (float_a // int_b), (float_a // float_b)
(2, 2.0, 2.0, 2.0)
>>> (-int_a // int_b), (-int_a // float_b), (-float_a // int_b), (-float_a // float_b)
(-3, -3.0, -3.0, -3.0)
>>> 

repr()とstr()

print文を使わないで循環小数を表示すると、小数点以下を丸めないでハードウェア上の値がそのまま表示する。
print文を使うと、丸めて人間が見やすい形にして表示する。

repr()はprint文なし、str()はprint文ありと同じ動きをする。

[kobakoba0723@fedora13-intel64 ~]$ python
Python 2.6.4 (r264:75706, Apr  1 2010, 02:55:51) 
[GCC 4.4.3 20100226 (Red Hat 4.4.3-8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 1/0.3
3.3333333333333335
>>> print 1/0.3
3.33333333333
>>> repr(1/0.3)
'3.3333333333333335'
>>> str(1/0.3)
'3.33333333333'
>>> 

16進と8進

通常の数値は10進数として扱われるので、8進/16進として扱う場合は特別な定義方法が必要

  • 8進数は先頭0で定義
  • 16進数は先頭0xで定義

内部的には8進/16進として扱われていても、画面出力は通常10進数となってしまう。
出力も8進/16進としたい時は、oct()/hex()を使う

[kobakoba0723@fedora13-intel64 ~]$ python
Python 2.6.4 (r264:75706, Apr  1 2010, 02:55:51) 
[GCC 4.4.3 20100226 (Red Hat 4.4.3-8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 01, 010, 0100
(1, 8, 64)
>>> 0x1, 0x10, 0x100
(1, 16, 256)
>>> o_num=010
>>> h_num=0x10
>>> o_num, h_num
(8, 16)
>>> oct(o_num), hex(h_num)
('010', '0x10')
>>> 

オーバーライドとオーバーロード

それぞれ別の現象を指す(当たり前か。。。)
Pythonでは、型がないのでオーバーロードをすることは出来ない。
より後に定義したもので上書きされてしまう。
参考:Javaの道:クラス-8(オーバーライドとオーバーロード)

オーバーライド

基底クラスで定義したメソッドを派生クラスで定義し直すこと。
Pythonでも出来た
(実行結果)

[kobakoba0723@fedora13-intel64 ~]$ python override_test.py
OverRideTest1: initial process done
OverRideTest2: initial process done
function test_func which defined in OverRideTest1
arg1 =  hogehoge
function test_func which defined in OverRideTest2
arg1 =  hogehoge

(override_test.py)

#!/usr/bin/env python

class OverRideBase:
  def __init__(self):
    print "OverRideBase: initial process done"
  
  def test_func(self, arg1):
    print "function test_func which defined in OverRideBase"
    print "arg1 = ", arg1

class OverRideTest1(OverRideBase):
  def __init__(self):
    print "OverRideTest1: initial process done"
  
  def test_func(self, arg1):
    print "function test_func which defined in OverRideTest1"
    print "arg1 = ", arg1

class OverRideTest2(OverRideBase):
  def __init__(self):
    print "OverRideTest2: initial process done"
  
  def test_func(self, arg1):
    print "function test_func which defined in OverRideTest2"
    print "arg1 = ", arg1

test1_sample = OverRideTest1()
test2_sample = OverRideTest2()
hoge = "hogehoge"

test1_sample.test_func(hoge)
test2_sample.test_func(hoge)
オーバーロード

同一クラス内で、引数の数、型、並びが異なるメソッドを複数定義すること
Pythonでは出来なかった。エラーが出て怒られた。
(実行結果)

[kobakoba0723@fedora13-intel64 ~]$ python overload_test.py
initial process done
function test_func which have 1 argument(arg1)
arg1 =  hogehoge
Traceback (most recent call last):
  File "overload_test.py", line 20, in <module>
    sample.test_func(hoge, piyo)
TypeError: test_func() takes exactly 2 arguments (3 given)

(overload_test.py)

#!/usr/bin/env python

class OverLoadTest:
  def __init__(self):
    print "initial process done"
  
  def test_func(self, arg1, arg2):
    print "function test_func which have 2 argument(arg1 and arg2)"
    print "arg1, arg2 = ", arg1, arg2
  
  def test_func(self, arg1):
    print "function test_func which have 1 argument(arg1)"
    print "arg1 = ", arg1

sample = OverLoadTest()
hoge="hogehoge"
piyo="piyopiyo"

sample.test_func(hoge)
sample.test_func(hoge, piyo)