この記事でやること
printやinputと言った関数を自分で一から定義するという記事です。
こんな人におすすめ
- 標準の関数がどんな動きをしているか興味のある人
- 自分で関数を再開発したい人
print関数の仕組み
print関数には、可変長のvalues、区切り文字になるsep、末尾に置かれる文字end、
ストリームを指定できるfile、フラッシュするかの指定flushと言った引数があります。
あと、sys.stdoutを自作ストリームに置き換えたことのある人は分かると思いますが
valuesとendは別々でwriteされています。
再現する方法
これらの引数は正直言って本家のものをパクってしまえばいいと思います(!?)
ただし、ちゃんと定義されていない型(ファイルストリームの型)や、オーバーロードされていて
無駄だと思われるflush引数とかは自分で改造してしまった方がいいでしょう。
(ファイルストリームをio.StringIOとして扱ったり、
flushをオーバーロードせずboolで固定)
追記: SupportsReadは_typeshedにありました
再現結果
import sys
import io
def my_print(*values: object, sep: str | None = " ", end: str | None = "\n", file: io.StringIO | None = None, flush: bool = False):
out_stream = file if file else sys.stdout
if sep:
out_stream.write(sep.join(map(str, values)))
else:
out_stream.write("".join(map(str, values)))
if end:
out_stream.write(end)
if flush:
out_stream.flush()
各オブジェクトをmapで文字列に変換して、sepを使ってjoinしています。
fileとstdoutは同じwriteメソッドが使えるので複雑にしなくてもOKです。
追記: よく考えたらwith文使ってないからstdoutの扱いが雑かも...
次回はinput関数を再定義してみようと思います!
最後まで読んでいただきありがとうございます!
おまけ: my_printと本家printを速度は変わんないっぽいです(少し誤差はあるものの)