Python
参考
-
イテレータ・イテラブル・ジェネレータ
-
async/await
-
その他
用語など
- イテレータ
- ジェレネータ
- コルーチン
- 並列化
- マルチスレッド
- マルチプロセス
- 非同期処理
- コールバック
- Promise
- async/awaite
まとめ
イテレータ・イテラブル
- イテラブル(iterable)
for 文で繰り返し処理ができるクラスのこと。
実装としては、__iter__() or __getitem__() を実装しているクラス。-
__iter__() はイテレータを意識したクラス
-
__getitem__() はリスト等を意識したクラス
lists = [1, 2, 3] for l in lists: print(l) # 書き換えると以下のように処理されている ite = [1, 2, 3].__iter__() # ite = iter([1, 2, 3]) while True: try: l = ite.__next__() # l = next(ite) except StopIteration: break print(l)
class Sequence: def __getitem__(self, index): if 0 <= index <= 3: return index * 2 else: raise IndexError seq = Sequence() print(seq[0]) print(seq[1]) print(seq[2]) print(seq[3]) for i in seq: print(i)
-
-
イテレータ(iterator)
実装としては、__iter__() or __next__() を実装しているクラス。
イテラブルであるため、for文でも使用できる。また、iter(), next() を使ってイテレーションできる。class Counter: def __init__(self, start, stop): self._counter = start self._stop = stop def __iter__(self): return self def __next__(self): if self._counter > self._stop: raise StopIteration() ret = self._counter self._counter += 1 return ret c = Counter(start=1, stop=3) c = iter(c) print(next(c)) # 1 print(next(c)) # 2 print(next(c)) # 3 print(next(c)) # StopIteration c = Counter(start=1, stop=3) for i in c: print(i)
ジェネレータ
-
ジェネレータ
関数定義で、yield 式を使うことで定義される。
通常の関数定義内で yield を使った場合は ジェネレータ関数 となり、
async def 関数定義内で使った場合は コルーチン関数(非同期ジェネレータ関数) となる。
Python 言語リファレンス Yield 式※通常の関数と異なり、ジェネレータ関数がコールされた場合、
すぐに関数内が実行されるわけではなく、ジェネレータイテレータオブジェクトを返す。
その後にジェネレータメソッド(generator.next() or generator.send())がコールされて初めて関数が実行されることに注意。-
next(generator)
=generator.send(None)
と考えていい?
def main(): a = simple() # 実行されずジェネレータを返すだけ print('first') x = a.send(None) # ここで初めてジェネレータが(yieldまで)実行される print(x) # third y = a.send('forth') print(y) # fifth def simple(): print('second') s = yield 'third' print(s) yield 'fifth' main() # first # second # third # forth # fifth
def echo(value=None): print("最初に 'next()' がコールされたときに実行が始まる.") try: while True: try: value = (yield value) except Exception as e: value = e finally: print("'close()' がコールされたときにクリーンアップを忘れないように") generator = echo(1) # ジェネレータイテレータオブジェクトを返すだけ print(next(generator)) # 最初に 'next()' がコールされたときに実行が始まる. # 1 print(next(generator)) # None print(generator.send(2)) # 2 generator.throw(TypeError, "spam") # TypeError("spam") generator.close() # 'close()' がコールされたときにクリーンアップを忘れないように
-
-
yield from
from のあとにイテラブルを指定する。
基本は、yield from iterable
=for item in iterable: yield item
def g(): for c in 'AB': yield c for i in range(1, 3): yield i print( list(g()) ) # ['A', 'B', 1, 2] def g2(): yield from 'AB' yield from range(1, 3)
本来の目的は、「一番外側の呼び出し側」と「一番内側のジェネレータ」間で値の送受信や例外処理できるようにすること。
def delegator(): while True: res = yield from subgenerator() print(res) def subgenerator(): while True: recv = yield if recv is None: break print(recv) return 'fin.' g = delegator() # ジェネレータイテレータオブジェクトを返すだけ next(g) g.send('A') # A g.send('B') # B g.send(None) # fin.
with
処理を終了する際に、必ず実行すべき処理があることが多い。
その場合、with を使って記述すると自動的に終了処理を行ってくれるようになる。
実装としては、__enter__() or __exit__() を実装しているクラス。
class WithClass:
@classmethod
def create(cls):
return WithClass()
def __init__(self):
print("init")
def hoge(self):
print("hoge")
def __enter__(self):
print("enter")
return self
def __exit__(self, ex_type, ex_value, trace):
print(f"exit: {ex_type} {ex_value} {trace}")
# return True # 例外を無視することできる
with WithClass() as w: # クラスのインスタンス化+処理開始
w.hoge() # 処理
# with を抜けた処理
# init
# enter
# hoge
# exit: None None None
# 同じ動作をする
with WithClass.create() as w:
w.hoge()
# 以下と等価
manager = WithClass()
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False
try:
w = value
w.hoge()
except:
hit_except = True
if not exit(manager, *sys.exc_info());
raise
finally:
if not hit_except:
exit(namager, None, None, None)
ソケット通信
A Complete Guide to Socket Programming in Python
-
ソケットは、抽象的なリモート接続管理のインターフェースである。
-
ソケットは、ローカルPC内またはネットワーク越しのPC同士の異なるプロセス間(通常はサーバとクライアント)の情報伝達を可能にする。
-
Pythonでは、ソケットを動作させるにはsocketライブラリを通して実現し、データ送受信のためのメソッドを持つソケットオブジェクトを提供している。
-
ソケットプログラミングはデータサイエンスで役に立つアプリケーションを持つ。
- Server
import socket server_ip = "127.0.0.1" server_port = 8000 def run_server(): try: # ソケットのインスタンス化 # socket.AF_INET : IPv4 # socket.AF_INET6: IPv6 # socket.SOCK_STREAM: TCP # socket.SOCK_DGRAM : UDP # socket.RAW_SOCKET : 低レベルプロトコル server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # ソケットをIPアドレスとポートに結び(bind)つける server.bind((server_ip, server_port)) # クライアントを待ち受ける # backlog: acceptしていない接続をキューにいれる最大数。0 = 1クライアントだけ受け入れる # 省略するとOSのデフォルト値が使われる(/proc/sys/net/core/somaxconn) server.listen(0) print(f"Listening on {server_ip}:{server_port}") # 接続を受け入れる(クライアントアクセスがあるまで処理が止まる) # 通常処理ではaccept() 後はクライアント接続がブロックされるので1クライアントしか処理できない # client_socket : 接続したクライアントのソケット # client_address: 接続したクライアントのIP情報 client_socket, client_address = server.accept() print(f"Accepted connection from {client_address[0]}:{client_address[1]}") # 通信処理 while True: # byte で取得される request = client_socket.recv(1024) request = request.decode("utf-8") if request.lower() == "close": client_socket.send("closed".encode("utf-8")) break print(f"Recieve: {request}") response = "accepted".encode("utf-8") client_socket.send(response) except Exception as e: print("Error occurred: {e}") finally: # 切断処理。システムリソースを解放する。 client_socket.close() print("Connection to client closed") # サーバを停止 server.close() run_server()
- Client
import socket server_ip = "127.0.0.1" server_port = 8000 def run_client(): # ソケットのインスタンス化 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # サーバに接続 client.connect((server_ip, server_port)) try: # 通信処理 while True: # メッセージ入力し、サーバへ送信 msg = input("Enter message: ") client.send(msg.encode("utf-8")[:1024]) response = client.recv(1024) response = response.decode("utf-8") if response.lower() == "closed": break print(f"Recieved: {response}") except Exception as e: print("Error occurred: {e}") finally: client.close() print("Connection to server closed") run_client()
並列化
その並列処理待った! 「Python 並列処理」でググったあなたに捧ぐasync, threading, multiprocessingのざっくりとした説明
並列処理
=> 本当に複数の処理を同時に実行する
並行処理
=> 複数の処理を効率よく切り替えながらあたかも
同時に実行する
async/await
-
Awaitable
await 式の中で使うことができるもの- コルーチン
- Task
- Future