PythonでUpcast/Downcast出来ない件と多態性のサンプル

継承・カプセル化・多態性

オブジェクト指向の必須要素はこれ。継承、カプセル化・多態性。
異種リストを書けば全部試せるので試してみる。

多態性実現のためにオブジェクトのUpcast/Downcastを調べようとしたら存在しない!。
結論として、PythonにおいてはオブジェクトのUpcast/Downcastは出来ない。

動的型付けなんで、Upcastは勝手に上位クラスだと思って触れば良いのだけど、
形だけでも上位クラスにキャストしておいた方が可読性は上がると思うので残念。

abstractメソッドを定義するだけでパッケージを要求するとか切ない。


from abc import ABCMeta, abstractmethod

# 抽象基底クラス
class Base:
     __attr = 100
     @abstractmethod
     def hoge(self):
          pass

class Derived1(Base):
     __attr = 200
     def hoge(self):
          print(self.__attr)

class Derived2(Base):
     __attr = 300
     def hoge(self):
          print(self.__attr)

vals = [Derived1(), Derived2()]
for val in vals:
     val.hoge()

なお、Downcastについては、以下のようにしている例がある。


class SubDerived2(Derived1):
     __attr = 500
     def hoge(self):
          print(self.__attr)

     def myfunc(self):
          print("myfunc is called")

derived = Derived2()
derived.__class__ = SubDerived2
derived.myfunc()

確かに、Upcastは動的型付けの範囲内だが、実現可能でDowncastは何らかの指示が必要で、
必要な方にだけ手段が用意されているのは合理的な気もする。

関数

defで定義する。最初の行に書いた文字列リテラルはdocstring。PHPDoc的なやつだろうか。
関数のスコープからローカル->グローバル->ビルトインの順にシンボルを参照できる。
関数スコープから外のスコープのシンボルは書けない。(global指定して初めて書ける)。

フィボナッチ数列。


def fib(n):
     """Print a Fibonacci series up to n."""
     a,b = 0,1
     while a < n:
          print(a,end=' ')
          a,b=b,a+b
     print()

fib(100)

# 0 1 1 2 3 5 8 13 21 34 55 89

キーワード引数も使える。


def myfunc(hoge,fuga=1):
     print(hoge)
     print(fuga)