おぼえがき

過ちては則ち改むるにうんぬんかんぬん

ダックタイピングについて(Python)

f:id:feci:20210726231508j:plain

Python3

 

Python3.8.5におけるダックタイピングについて。

class Cx(object):
  def __init__(selfpas=123):
    self.pas = pas
  def fcx(self):
    if self.pas == 123:
      print('あいうえお')
    else:
      raise Exception

class Cy(Cx):
  def __init__(selfpas):
    if pas == 123:
      super().__init__(pas)
    else:
      raise ValueError

class Cz(Cx):
  def __init__(selfpas):
    if pas != 123:
      super().__init__(pas)
    else:
      raise ValueError

cy = Cy(123)
cy = Cy(456)  #ValueError
cz = Cz(456)
cz = Cz(123)  #ValueError

class Ca(object):
  def __init__(selfa=None):
    self.a = a
  def fa(self):
    print('あいうえお')
  def fb(selfcx):
    cx.fcx()

ca = Ca()
ca.fb(cy)  #あいうえお
ca.fb(cz)  #Exception

大変残念なことに講座を見ても検索しても「ダックタイピング」という概念についてまったく理解できなかったので、私の言葉で説明する代わりにネットで検索してヒットしたダックタイピングについての説明を3つほどご紹介させていただきます。

 

①:ダックタイピングとは、動的型付けオブジェクト指向プログラミング言語で使われる型付けスタイルのことです。

 

②:ダックタイピングとは、どんな特定のクラスとも紐付かないインタフェースを定義することです。

 

③:ダックタイピングはオブジェクトを主な対象にし、そのオブジェクトの型名ではなく、そのオブジェクトが現在保持しているプロパティとメソッドに従って現行演算での適合性および計算可能性の是非を判定することを特徴にした構造的型付けの一種です。

 

 

これがダックタイピングという概念らしいです。

 

これ、意味が分かりますでしょうか?

ふんわりしすぎてて、私にはなんのこっちゃさっぱり分かりません。

 

そして、上記のスクリプトはダックタイピングを説明したものらしいです。

ダックタイピングについての解説動画のはずなのに、このスクリプトのどの部分がどうダックタイピングなのかというような説明は、なぜか一切ありませんでした。

いや、そんなんで分かるわけないやん(正論)。

 

まあなんかダックタイピングとは上記のようなものらしいです。

上記のダックタイピングの説明とスクリプトを見て、ダックタイピングという概念がどういうものか具体的に理解できたでしょうか?

 

理解できたあなたはとってもすごいです。

私のお粗末なCPU(脳)では、具体的に何がどういうことなのやらさっぱり理解できませんでした。

 

 

〇追記

あまりにも意味不明で悶々としていたのですが、wikiに有料講座なんかよりもぜんぜん分かりやすいコード例がありましたので引用させていただきました。

 

これがスクリプト

class Duck:
    def swim(self):
        print("Duck swimming")
   def fly(self):
        print("Duck flying")

class Whale:
    def swim(self):
        print("Whale swimming")

for animal in [Duck(), Whale()]:
    animal.swim()
    animal.fly()

 

んで、これが上記スクリプトの出力結果です。

Duck swimming
Duck flying
Whale swimming
AttributeError'Whale' object has no attribute 'fly'

 

上記のスクリプトでは、DuckとWhaleという2つの別クラスの中に、swimという同名のメソッドが定義されています。

そしてDuckクラスにだけ、追加でflyメソッドも定義されています。

 

そしてfor文を使ってanimal変数の中にDuck()とWhale()を入れていきます。

第1引数がDuck()なので、最初はDuckクラスのインスタンスとしてanimal.swim()を実行していきます。

そして、そのまま続けてanimal.fly()も実行します。

 

とうぜん、どちらのメソッドも呼び出すことができます。

 

for文なので、第1引数の処理が終わったら、次は第2引数の処理を実行していきます。

なので、次はanimalをWhaleクラスのインスタンスとして実行していきます。

 

animal.swim()と記述すると、Whaleクラスのswimメソッドを呼び出すことができます。

しかしWhaleクラスにはflyメソッドが定義されていないので、次の行のanimal.fly()を実行するとAttributeErrorが出ます。

 

このように、違うクラスのメソッドなのに「名前が同じ」なので同じ記述で問題なくそのメソッドを呼び出せてしまいます。

こういう仕様(機能?)のことを、動的型付けであったりダックタイピングと呼ぶみたいです。

 

つまりダックタイピングとは、「クラス型が違っても同名のメソッドを持っていれば同じように処理するよ」ということらしいです。

このダックタイピングと対照的な処理が、JAVAのinterfaceなどに使われている静的型付けなのでしょうね。

 

静的型付けだと「Aは〇〇ができる」と考えるのに対して、動的型付けだと「〇〇ができるのはAだ」と考えるらしいです。

ダックタイピングは、後者の「swimメソッドが実行できるのは〇〇だ」という考え方にもとづいて処理されるスクリプトだということなのでしょうね。

 

うん。完璧ではありませんが、少なくとも講座を見た後よりはダックタイピングという概念について理解できたような気がします。

 

 

以上です。