Python(ダック・タイピング)

Pythonの面白い機能としてダック・タイピングがあります。
これは、クラスの型が違えど、同じメソッドを持っていれば同様に処理するという手法です。
# ダック・タイピング(クラスの型が違えど同じメソッドがあれば同様に処理する)
from abc import ABCMeta,abstractmethod

# 抽象基底クラス
class Animal(metaclass=ABCMeta):
    @abstractmethod
    def sound(self):
        pass

    @abstractmethod
    def walk(self):
        pass

# あるインスタンスのsoundとwalkメソッドを実行
def test_duck(it):
    it.sound()
    it.walk()

class Duck(Animal):
    def sound(self):
        print("ガァガァ")
    def walk(self):
        print("アヒルが歩く")

class Dog(Animal):
    def sound(self):
        print("ワンワン")
    def walk(self):
        print("犬が歩く")

class Cat(Animal):
    def sound(self):
        print("ニャーニャー")
    def walk(self):
        print("猫が歩く")

ahiru = Duck()
test_duck(ahiru)

inu = Dog()
test_duck(inu)

neko = Cat()
test_duck(neko)
ダック・タイピングと抽象基底クラスを組み合わせたプログラムですが、抽象基底クラスを用いなくても、ダック・タイピングでは必要なメソッドがすでに定義されていることを前提としてプログラムを組むことができます。
(個人的に抽象基底クラスを組み合わせることで、より確実にダック・タイピングを利用できると思ってます。)
# ダック・タイピング(クラスの型が違えど同じメソッドがあれば同様に処理する)
from abc import ABCMeta,abstractmethod

# 抽象基底クラス
class Animal(metaclass=ABCMeta):
    @abstractmethod
    def name(self):
        pass

    @abstractmethod
    def legs(self):
        pass

class Turu(Animal):
    def name(self):
        return "鶴"
    def legs(self):
        return 2

class Kame(Animal):
    def name(self):
        return "亀"
    def legs(self):
        return 4

class Tako(Animal):
    def name(self):
        return "タコ"
    def legs(self):
        return 8

class Ika(Animal):
    def name(self):
        return "イカ"
    def legs(self):
        return 10

# 鶴亀算を解く関数
def calc_turukame(animal1,animal2,heads,legs):
    _a1leg = animal1.legs()
    _a2leg = animal2.legs()
    _a1name = animal1.name()
    _a2name = animal2.name()

    """ 実際の足の数と仮にすべてanimal1だと仮定した場合の足の数との差を計算し、
    それをanimal1とanimal2の足の数の差で割ると、animal2の数になる"""
    _a2num = (legs - (_a1leg * heads)) // (_a2leg - _a1leg)
    _a1num = heads - _a2num
    print("---")
    print("頭=",heads,"足=",legs)
    print(_a1name,"=",_a1num)
    print(_a2name,"=",_a2num)
    return (_a1num, _a2num)

# モジュールでない時は以下を実行
if __name__ == "__main__":
    # 鶴亀算で問題を解く
    calc_turukame(Turu(),Kame(),heads=10,legs=28)
    calc_turukame(Tako(),Ika(),heads=11,legs=100)
ダック・タイピングを用いた鶴亀算のプログラムです。
calc_turukameメソッドのように特定の型のクラスを指定する必要がなく、数える動物のインスタンスを渡せば良い点で、ダック・タイピングを活用することができます。 if name == "main__":はこのプログラムをモジュールとして扱う場合、これ以降のプログラムが実行されないようにしています。
Pythonではモジュールとして外部のプログラムから取り込まれるとき、特殊変数「 __name
」にはモジュールの名前が設定され、メインプログラムとして実行されるときには「 __main__ 」が設定される仕組みになっています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

Python

前の記事

Python(抽象基底クラス)
Python

次の記事

Python(ユニットテスト)