Pythonで結局のところ、型を意識していないと辛いのですが...

f:id:ts0818:20210310114426j:plain

codezine.jp

 オープンソースPython機械学習ライブラリPyTorch開発チームは、最新版となる「PyTorch 1.8」を3月4日(現地時間)にリリースした。

Python用機械学習ライブラリ「PyTorch 1.8」がリリース、科学計算用フロントエンドAPIの追加など変更多数:CodeZine(コードジン)

⇧ ますます「機械学習」のライブラリが充実していく世の中に我々は生きているということですかね、どうもボクです。

そんなこんなで、Pythonについてです。

レッツトライ~。 

 

Pythonは動的型付け言語である!

Wikipedia様の御宣託を見分することにより、我の曇り切ったPythonへの知見が解消されんことを、恐み恐み(かしこみかしこみ)乞祷(こいのみ)奉(たてまつ)らむ、ということで、 

Python動的に型付けされていて、ガベージコレクションされている。構造化(特に手続き型)、オブジェクト指向関数型プログラミングを含む複数のプログラミングパラダイムをサポートしている。Pythonは、その包括的な標準ライブラリのため、しばしば「バッテリーを含む」言語と表現される。

Python - Wikipedia

⇧ みんな大好きPythonは、「動的型付け言語」ですと。

「動的型付け言語」、確かに、コーディングした内容を逐次実行できるから便利なんですが、「型」を定義しなくてもコーディングできてしまうために、コーディングの意図ってのが見え辛いってことがあるあるかと。

ただ、Pythonもコーディングにおける「型」についての問題意識は持っていたのかは分かりませんが、

docs.python.org

typing --- 型ヒントのサポート

バージョン 3.5 で追加. 

ソースコード: Lib/typing.py

注釈

 

Python ランタイムは、関数や変数の型アノテーションを強制しません。 型アノテーションは、型チェッカー、IDE、linterなどのサードパーティーツールで使われます。


このモジュールは PEP 484PEP 526PEP 544PEP 586PEP 589PEP 591 によって規定された型ヒントへのランタイムサポートを提供します。 最も基本的なサポートとして Any、 Union、 Tuple、 Callable、 TypeVar および Generic 型を含みます。 完全な仕様は PEP 484 を参照してください。 型ヒントの簡単な導入は PEP 483 を参照してください。

https://docs.python.org/ja/3/library/typing.html

Python 3.5 から「type hinting」のサポートが導入されてますと。

まぁ、コーディングに使用してるエディターなんかの個々人の環境にお任せということで、Pythonランタイム自体は、コーディング時に「型」を意識してようがしてまいが、どうでも良いよってスタンスみたいですね...

Oh, my gosh...

なので、意識高い系?であれば、「静的型付け言語」みたいに、「型」を意識したコーディングを行おうと思えば行えるみたいですかね。 

 

結局のところ、型を意識しないと駄目やん?

で、本題。

「型」を意識していないと、駄目な例が「len()」関数、というか、何か値に対して処理する関数すべてにおいて言えると思うので、結局のところ、すべてにおいて「型」を意識する必要は少なからず出てくるとは思われますが...

で、「len()」関数のドキュメントを確認してみると、

docs.python.org

len(s)

オブジェクトの長さ (要素の数) を返します。引数はシーケンス (文字列、バイト列、タプル、リスト、range 等) かコレクション (辞書、集合、凍結集合等) です。

https://docs.python.org/ja/3/library/functions.html#len

⇧ ってな感じで、「『オブジェクト』の『長さ(要素の数)』を返します。」ってあるんだけど、引数として受け付けることのできる「型」は、

  • シーケンス
    • 文字列
    • バイト列
    • タプル
    • リスト
    • range
  • コレクション
    • 辞書
    • 集合
    • 凍結集合

 等、である必要がありますと。(「等」ってのが曖昧な感じになってるので、ハッキリさせてくれんかね、と思ってしまう私は心の狭い人間なのだろうか...)

まぁ、この時点で、ドキュメントがイケてないと思えて仕方ないんだけど、無償でドキュメントを作ってくださっている方々への感謝を忘れてはいけませんよ!

そもそもとして、Pythonってどんな「型」あるんだっけ?

docs.python.org

以下のセクションでは、インタプリタに組み込まれている標準型について記述します。

主要な組み込み型は、数値、シーケンス、マッピング、クラス、インスタンス、および例外です。

https://docs.python.org/ja/3/library/stdtypes.html

コレクションクラスには、ミュータブルなものがあります。コレクションのメンバをインプレースに足し、引き、または並べ替えて、特定の要素を返さないメソッドは、コレクション自身ではなく None を返します。

https://docs.python.org/ja/3/library/stdtypes.html

⇧ ってな感じで、「型」の全量が無茶苦茶に把握し辛いんですと、っていうか、ドキュメントの全てをなめるように読み込まないといけないんか...

いや、すみません、失言でした、ドキュメント読むの楽しいな~。

 

Pythonの組み込み関数の内が1つ、「len()」関数で見事に躓く

ズバリ、「len()」関数という、超初歩的な関数で躓いたことを反省いたします... 

で、今回、「janome」っていう「自然言語処理」で「形態素解析」する際に使用するライブラリを使ってたのですが(事前に、Python仮想環境内でpipを使い「janome」をインストールしておく必要があります)、

import janome
def get_target(target_list):
    target = []
    # Tokenizerオブジェクトのインスタンスを生成
    t = Tokenizer(wakati=False)

    for target in target_list:
        # tokenize関数を用いてtargetを形態素解析
        target_row = t.tokenize(target)
        if len(target_row) > 0:
            # 形態素結果のtarget_now[0]を取得
            target.append(target_row[0].surface)
    return target

ってな感じでコーディングしたところ、

TypeError: object of type 'generator' has no len()

⇧ ってなエラーが出たんだけど、

コーディングの内容を、 

import janome
def get_target(target_list):
    target = []
    # Tokenizerオブジェクトのインスタンスを生成
    t = Tokenizer(wakati=False)

    for target in target_list:
        # tokenize関数を用いてtargetを形態素解析
        target_row = [i.surface for i in t.tokenize(target)]
        if len(target_row) > 0:
            # 形態素結果のtarget_now[0]を取得
            target.append(target_row[0])
    return target

⇧ ってな感じにしたところ、無事にエラーが解消されましたと。

エラーの原因は、Pythonの「len()」関数が「generator」型を扱うことができない、ってことらしいですね。

 

qiita.com

そもそもジェネレータには2つの意味がある(!)
ジェネレータは文脈によって意味が異なり、

の2つの意味がある(参考)

[python]イテレータとジェネレータの違い[これが真実] - Qiita

それぞれの意味は、

  • ジェネレータ関数
    • ジェネレータイテレータというオブジェクトを返す関数
    • yield式を持つ
  • ジェネレータイテレータ
    • ジェネレータ関数で生成されるオブジェクト

このジェネレータイテレータイテレータの一種。

[python]イテレータとジェネレータの違い[これが真実] - Qiita

⇧ ってことらしいので、むっちゃ紛らわしいやん...

 

まぁ、結局のところ、Pythonは「動的型付け言語」であるからして「型」とかあまり意識されないでコーディングできてしまうことがあるあるだとは思うのですが、「型」を意識してないと躓きやすいってことですかね...

Pythonはいろんなライブラリが手軽に使えるというのは利点かもしれませんが、「型」は気にするようにしときたいですかね...

何て言うか「機械学習」に関係ない、一般的なPythonのコーディングについても詰まるところが多くて疲れる...

「型」を意識的にコーディングしてくれる文化が根付いてくれれば助かるんですけどね...

今回はこのへんで。