Python

参考文献

    • #strftime-strptime-behavior に strptime() の書式コードがある。

Snippets

コンテキストマネージャ型

import http.client
import json

class MyClient:
    def __init__(self, host='localhost', port=8080):
        self.host = host
        self.port = port
    def __enter__(self):
        self.conn = http.client.HTTPConnection(self.host, self.port)
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.conn.close()
    def get(self, url):
        self.conn.request('GET', url)
        resp = self.conn.getresponse()
        if resp.status == 200:
            data = json.loads(resp.read().decode())
            return data
        else:
            raise Exception(f'Failed: {resp.status} {resp.reason}')

with MyClient() as cli:
    data = cli.get('/bentou?type=A')
    print(data)

contextlib.contextmanager デコレータ

import http.client
import json
from contextlib import contextmanager

@contextmanager
def my_connection(host='localhost', port=8080):
    conn = http.client.HTTPConnection(host, port)
    try:
        yield conn
    finally:
        conn.close()

with my_connection() as conn:
    conn.request('GET', '/bentou?type=A')
    resp = conn.getresponse()
    data = json.loads(resp.read().decode())
    print(data)

フィボナッチ数列を返すイテレータオブジェクト

イテレータオブジェクトの構成プロトコルは、イテレータオブジェクト自体を返す
__iter__()
と次のアイテムを返す
__next__()
とのことなので[2]、これらのメソッドを実装する。以下のイテレータオブジェクトは100に達するまでフィボナッチ数列を出力する。
class Fibonacci:
    def __iter__(self):
        print('===== __iter__() was just called. =====')
        self.a = 0
        self.b = 0
        return self
    def __next__(self):
        if self.b >= 100:
            raise StopIteration()
        if self.b == 0:
            c = 1
        elif self.a == 0:
            c = 1
        else:
            c = self.a + self.b
        self.a = self.b
        self.b = c
        return c

fi = Fibonacci()
for x in fi:
    print(x)
for x in fi:  # 2回目も可能.
    print(x)
===== __iter__() was just called. =====
1
1
2
3
5
8
13
21
34
55
89
144
===== __iter__() was just called. =====
1
1
2
3
5
8
13
21
34
55
89
144
いくつに達したら終わるかを毎回変更することもできる。
import random

class Fibonacci:
    def __iter__(self):
        print('===== __iter__() was just called. =====')
        self.a = 0
        self.b = 0
        self.threshold = random.choices([5, 10, 20, 30])[0]
        return self
    def __next__(self):
        if self.b >= self.threshold:
            raise StopIteration()
        if self.b == 0:
            c = 1
        elif self.a == 0:
            c = 1
        else:
            c = self.a + self.b
        self.a = self.b
        self.b = c
        return c

文字列を datetime 型に変換しユニックス秒に変換する

datetime.datetime.strptime() で datetime 型にできる。timestamp() メソッドでユニックス秒にできる。タイムゾーン情報をパースしないと datetime 型は自分のタイムゾーンについて無知になる。その場合でも timestamp() メソッドではシステムのタイムゾーンが適用される。タイムゾーン情報をパースさせれば datetime 型は自分のタイムゾーンを認識する。日本時間の1時より協定世界時の1時の方が未来である。
import datetime

s = '2022-03-13 01:23:45'
dt = datetime.datetime.strptime(s, '%Y-%m-%d %H:%M:%S')  # naive
ts = dt.timestamp()  # ここでローカル時刻として UNIX 秒化される
print(dt, dt.tzinfo)
print(ts)
print(datetime.datetime.fromtimestamp(ts))

s = '2022-03-13 01:23:45+09:00'
dt = datetime.datetime.strptime(s, '%Y-%m-%d %H:%M:%S%z')  # aware
ts = dt.timestamp()
print(dt, dt.tzinfo, dt.tzinfo.utcoffset(dt))
print(ts)
print(datetime.datetime.fromtimestamp(ts))

s = '2022-03-13 01:23:45+00:00'
dt = datetime.datetime.strptime(s, '%Y-%m-%d %H:%M:%S%z')  # aware
ts = dt.timestamp()
print(dt, dt.tzinfo, dt.tzinfo.utcoffset(dt))
print(ts)
print(datetime.datetime.fromtimestamp(ts))
2022-03-13 01:23:45 None
1647102225.0
2022-03-13 01:23:45

2022-03-13 01:23:45+09:00 UTC+09:00 9:00:00
1647102225.0
2022-03-13 01:23:45

2022-03-13 01:23:45+00:00 UTC 0:00:00
1647134625.0
2022-03-13 10:23:45
上のコードに示しているように datetime.datetime.fromtimestamp() でユニックス秒から datetime 型を復元できるが、このとき明示的にタイムゾーンを指定しないと datetime 型は自分のタイムゾーンについて無知になる。
ts = 1647102225.0

dt = datetime.datetime.fromtimestamp(ts)
print(dt, dt.tzinfo)

dt = datetime.datetime.fromtimestamp(ts, datetime.timezone(datetime.timedelta(hours=9)))
print(dt, dt.tzinfo)

dt = datetime.datetime.fromtimestamp(ts, datetime.timezone(datetime.timedelta(hours=0)))
print(dt, dt.tzinfo)
2022-03-13 01:23:45 None

2022-03-13 01:23:45+09:00 UTC+09:00

2022-03-12 16:23:45+00:00 UTC