nikkie-ftnextの日記

イベントレポートや読書メモを発信

田中琴葉ちゃんをPythonにやらせよう。「引数の型ヒントをlistにしてはいけません」と伝えるスクリプトを作る

こちらのツイート解題です

目次

技書博で頒布した『引数の型ヒントをlistにしてはいけません』

公式ドキュメントに「引数の型ヒントをlistにしてはいけません」(※意訳)って書いてあるのですが、どうも浸透していないように見受けられるので、このたび頒布しました。
私は、ドキュメントに沿って書かれたPythonを世界に増やしたいんです!

本エントリはおまけです。

田中琴葉ちゃん

重いことで知られます1

ミリシタを遊んでいると「控え室で野球をしてはいけません」という貼り紙が目につきます。
これは琴葉ちゃんによるもの

「引数の型ヒントをlistにしてはいけません」って「控え室で野球をしてはいけません」っぽくないですか?2
ぽいですよね3

書籍で著したのでコードでも著していきましょう

Pythonスクリプト化した琴葉ちゃん「引数の型ヒントをlistにしてはいけません」

Pythonの見た目(構文)って面白いと興味を持った経験4が活きました。

NodeVisitorを継承して、「引数の型ヒントをlistにしてはいけません」を検出するVisitorを定義しています5
https://docs.python.org/ja/3/library/ast.html#ast.NodeVisitor

関数定義を見たところ、関数の引数はargらしいことが分かります。
https://docs.python.org/ja/3/library/ast.html#ast.FunctionDef

そこで、visit_argを定義しました。
https://docs.python.org/ja/3/library/ast.html#ast.arg

arg is a raw string of the argument name; annotation is its annotation

ast.argannotation属性に型ヒントが入っているようなので、そこがlist(をはじめとする具象コレクション)になっているかを確認しています(なっていたら「いけません」と通知します)。

以下のコードを渡したときに

from collections.abc import Iterable

print("Hello, world!")


def plus_one_ng(numbers: list[int]) -> list[int]:
    return [n + 1 for n in numbers]


def plus_one_ok(numbers: Iterable[int]) -> list[int]:
    return [n + 1 for n in numbers]
Fix at 6:16
arg(arg='numbers', annotation=Subscript(value=Name(id='list', ctx=Load()), slice=Name(id='int', ctx=Load()), ctx=Load()))

はああ、「引数の型ヒントをlistにしてはいけません」、できた〜🙌

終わりに

「引数の型ヒントをlistにしてはいけません」を、ASTを操作して実装してみました。
気が向いたら琴葉ちゃんGitHubPyPIに置いちゃうかもしれません。

探せばもっとうまい実装がある気もします。
70億人いて私しか考えつかないというはずはないですから。
静的解析をするツールを覗いてみて、機能追加しやすくなるような実装も考えてみたいです。
このあたりにピンとくる方からのタレコミ、お待ちしています!

念のためですが、タイトルから、琴葉ちゃんが退屈なことって主張するつもりはこれっぽっちもないですからね!
O'Reilly Japan - 退屈なことはPythonにやらせよう 第2版


  1. ここに込めてます! オレンジノキオク、プラチナランカー!! #ミリシタ - nikkie-ftnextの日記
  2. 私があえて琴葉ちゃんに寄せたワーディングをしているというのもあります
  3. 導き出される結論としては、nikkieは琴葉ちゃんだったということです
  4. 抽象構文(AST)に対して、具象構文もあります
  5. Visitorパターン!