モブプロな人たちのブログ

横浜で Web サービス開発しているエンジニアの日記です。Python 大好き Flask 大好き。たまに SpriteKit でゲーム開発も。

Python の Type Hints を今更ながら勉強してみる

最近、開発環境をより便利にするために色々調査していて、今更ながら Type Hints が気になってきたので勉強してみることにしました。

Type Hints とは Python 3.5 から導入されたものです。

業務で扱っている Python が 2 系のため、そもそも対象外と考えて今まであまり意識したことがなかったのですが、2 系でも対応できるような書き方があったんですね。

んで、PyCharm などの IDE を使っているとそれらを自動的に良い感じにやってくれることが分かり、

こりゃキャッチアップしとかにゃマズイ!

という感じです。

で、実際にコードを書いて試してみたのですが、

def get_full_name(first_name, last_name):
    # type: (str, str) -> str
    return first_name + ' ' + last_name


if __name__ == '__main__':
    full_name = get_full_name('Stevie', 'Wonder')

ここまで書いて、その後に full_name. と打つと、

f:id:kaorr_mob:20180119225515p:plain

すんばらしいですね。

ぜひ、今後は積極的に使っていきたいと思います。

Python で a == 1 and a == 2 and a == 3 が True になるやつ、の補足

先日の記事を見たチームの人から、

わけわからん!

と指摘を受けてしまったので、少し補足します。

先日の記事とは↓のことです。

Python で a == 2 and a > 3 and a < 4 を True にしてみる

コードで見た方が分かりやすいと思うので、先日とは違う感じで書いてみました。

class A:
    def __init__(self, start):
        self.number = start

    def __eq__(self, target):
        print(f'{self.number} == {target}')
        return True

    def __gt__(self, target):
        print(f'{self.number} > {target}')
        return True

    def __lt__(self, target):
        print(f'{self.number} < {target}')
        return True


a = A(1)

if a == 2 and a > 3 and a < 4:
    print('GOOD!')

# 1 == 2
# 1 > 3
# 1 < 4
# GOOD!

以上です。

はい、補足とか言いながら全然補足してないですね、あはは。

Python で a == 1 and a == 2 and a == 3 が True になるやつ

Twitter を眺めていたら、何やら面白そうな記事があったので、Python で真似てみることにします。

class A:
    def __init__(self, start):
        self.number = start

    def __eq__(self, target):
        if self.number != target:
            return False

        self.number += 1
        return True


a = A(1)

if a == 1 and a == 2 and a == 3:
    print('GOOD!')

うん、サクッとやってみましたが、なかなか面白いですね。

(実用性があるのかはよく分かりませんが・・・!)

こういう小さいネタを数多く重ねていくと、知らぬ間に言語仕様に詳しくなったり・・・しないか。

Python で unittest ですべてをテストする

「Effective Python」を久しぶりに読み返して、当時は特に何も思わなかった箇所に引っかかったのでメモを残しておきますシリーズ第6弾。

Effective Python ―Pythonプログラムを改良する59項目

Effective Python ―Pythonプログラムを改良する59項目

Python で unittest ですべてをテストする

ひー!!

いや、ホントそうですよね。

こじんまりと Python 使っていたときはそこまで意識してなかったですが、やはり unittest 大事ですよね。(まぁ、Python に限らずすべての言語で必要だと思いますが。)

写経した結果をぺたりとすると、

# utils.py

def to_str(data):
    if isinstance(data, str):
        return data
    elif isinstance(data, bytes):
        return data.decode('utf-8')
    else:
        raise TypeError('Must supply str or bytes, found: %r' % data)

↑がテスト対象の関数で、

# utils_test.py

from unittest import TestCase, main
from utils import to_str


class UtilsTestCase(TestCase):
    def test_to_str_bytes(self):
        self.assertEqual('hello', to_str(b'hello'))

    def test_to_str_str(self):
        self.assertEqual('hello', to_str('hello'))

    def test_to_str_bad(self):
        self.assertRaises(TypeError, to_str, object())


if __name__ == '__main__':
    main()

↑がテストコードです。

うん、良いですね、unittest って。

Python で リストを返さずにジェネレータを返すことを考える

「Effective Python」を久しぶりに読み返して、当時は特に何も思わなかった箇所に引っかかったのでメモを残しておきますシリーズ第5弾。

Effective Python ―Pythonプログラムを改良する59項目

Effective Python ―Pythonプログラムを改良する59項目

Python で リストを返さずにジェネレータを返すことを考える

ジェネレータ! あまり使ったことなかったです。

リストだとメモリを食いつぶす恐れのある処理などで使うと便利そうというのは分かっていても、なかなかその実装にまでたどり着きませんでした・・・。

実際にコードで見てみると分かりやすいですね。

def index_words(text):
    result = []
    if text:
        result.append(0)
    for index, letter in enumerate(text):
        if letter == ' ':
            result.append(index + 1)
    return result

def index_words_iter(text):
    if text:
        yield 0
    for index, letter in enumerate(text):
        if letter == ' ':
            yield index + 1

if __name__ == '__main__':
    address = 'Four score and seven years ago...'

    result = index_words(address)
    print(result)

    result = index_words_iter(address)
    print(list(result))

index_words() がリストを返すメソッドで、index_words_iter() がジェネレータを返すメソッドです。

メモリ関係の話は抜きにしても、コード自体がスッキリとして、とても見やすいですね!

今後は、リストではなくジェネレータに出来ないか、検討する時間を設けてみたいと思います。