ソニックの部屋

主にプログラミングに関する記事を投稿します

「シリコンバレー一流プログラマーが教える Pythonプロフェッショナル大全」を読む

気になった用語等をまとめる

第1-7章_入門編

学んだこと

  • 複数行にわたる文字列の出力
print("""
1
2
3
""")

>>
←空行
1
2
3
←空行
  • 行の最後の\は次の行に続くため改行されない
  • メソッドとは変数等の後に.を付けその後に書いて実行する命令(.の前にある変数等の型と結び付けられている)
  • リストと辞書は参照渡し
  • リストの重複削除にはsetを使う
l = [0, 1, 1, 2]
a = set(l)
print(a)

>> {0, 1, 2}
# 集合になる
  • 値が入っていないことを判定するテクニック
a = 0
if a:
  print(OK)
else:
  print(NG)

>> NG
# 数値が0の場合はFalseとなるためNGとなる(0以外の数値はTrue)
  • Falseになるのは0, 空の文字列・リスト・辞書・タプル
  • inputで入力した内容は必ず文字列になる
  • rangeの数値をforループで使わない時は_を使う(単純にrange分だけ繰り返したい時)
for _ in range(10):
  • 辞書のforループはキーが取り出される
  • 辞書でバリューを取り出したい時はitems()を使う
d = {"a": 1, "b": 2}
for k, v in d.items():
  • 関数の呼び出しは後で
  • 参照渡しのものはデフォルト引数に使わない
  • 関数内関数をクロージャーと言い、外側の関数に渡した引数の値が関数内関数でも保持されている
def circle_area_func(pi):
  def circle_area(radius):
    return pi * radius * radius
  return circle_area

ca1 = circle_area_func(3.14)  # 関数内関数を実行するには外側の関数の返り値を変数に格納し実行する必要がある
print(ca1(10))

>> 314.0
  • デコレーターは関数を実行する前後に処理を加えたい時に少ないコード量で書ける
  • ジェネレーターは反復処理、returnがない、他の処理が入っても次の要素の状態を保持するため、重たい反復処理を小分けにするのに便利
  • コマンドライン引数はsys.argvで取り出す
# python app.py b
import sys

print(sys.argv)

>> [app.py, b]
  • ファイルをモジュール、ディレクトリをパッケージ
  • init.pyがあることによりパッケージとなる(v3.3以降は任意)
  • 「import パッケージ.モジュール」で読み込む
  • 「from パッケージ import モジュール」で読み込む
  • 組み込み関数はimport不要、標準ライブラリはimport必要
  • クラスのメソッドには必ず引数にselfが必要
class Preson:
  def __init__(self)  ←必ずselfが必要
  • クラス内で自身のインスタンス変数とメソッドを読み出す際は必ずselfが必要
  • 変数名に_を付けてプロパティを設定するとクラス外から読み込みは可能だが書き換えは不可となる
class AdvanceCar:
  def __init__(self, _enable_auto_run=False):
    self._enable_auto_run = enable_auto_run  ←変数名に_を付ける

  @property  ←プロパティのゲッター
  def enable_auto_run(self):
    return self._enable_auto_run  ←変数を返す

advanced_car = AdvancedCar()
print(advanced_car.enable_auto_run)  ←False(呼び出しの括弧は不要)

advanced_car.enable_auto_run = True  ←エラーとなる(書き換え不可)
-----------------------------------------
# プロパティに外から値を設定できるようにしたい場合はセッターを作る
  @enable_auto_run.setter  ←プロパティのセッター
  def enable_auto_run(self, is_enable):
    self._enable_auto_run = is_enable

advanced_car.enable_auto_run = True  ←エラーとならない(書き換え可能)
  • プロパティとセッターは特定の条件に合致した時にだけ書き換え可能にしたい時に役立つ
  • クラス外から読み込みも不可にするには変数名に__(アンダースコア二つ)を付けてプロパティのゲッターを用いる
  • 抽象クラスは継承されて使うことを前提にしたものだが、Pythonでは非推奨のためパス
  • 多重継承は左のクラスのメソッドが優先される
class PersonCarRobot(Car, Person):  ←Carが優先
  ...
  • クラス変数で異なるオブジェクト間でも同じ値を共有する
class Preson:
  kind = "human"  ←ここで定義

  def who_are_you(self):
    print(self.kind)  ←呼び出す際はインスタンス変数と同じくselfを付ける

a = Person()
a.who_are_you()
b = Preson()
b.who_are_you()
  • オブジェクトとして生成される前にメソッドにアクセスするにはクラスメソッドを使う
  • 同じような使い方でスタティックメソッドがある
  • スタティックメソッドはクラスのデータにアクセスせずクラスとの関連性が薄いもの
  • 特殊メソッド(strなど)によりオブジェクトの文字列表現、足し算、比較等ができる
  • Windowsは改行が2文字分となるためファイル書き込みや読み込みの際はnewlineを使う
  • os, pathlib, glob等でファイル操作

第8-13章_応用編

学んだこと

コンフィグとロギング

  • 標準ライブラリのconfigparser, yamlでコンフィグ(設定値のスクリプト)の設定を行う
  • 標準ライブラリのloggingでログを出力する
import logging

logging.basicConfig(level=logging.INFO)  ←ログレベルの設定
logging.info('info')  ←ログの表示
  • getLoggerによりロガーというログを使い分けるオブジェクトを作る
import logging

logger = logging.getLogger(__name__)  ←__name__を渡すのがコツ
  • 出力先の設定はハンドラーを作成してロガーに渡す
import logging

h = logging.FileHandler('logtest.log')  ←logtest.logに出力する
logger.addHandler(h)  ←ロガーにハンドラーを渡す
  • フィルタを使ってログ出力の条件を設定する→logging.Filterを継承したクラスを作成し条件設定
  • ロガーの設定ファイルを読み込んで使う→logging.config.fileConfig('logging.ini'を使う)
  • メールを送信するには標準ライブラリのemail, smtplibを使う
from email import message
import smtplib

... # SMTPサーバー名やポート番号を設定していく
  • ログをメール送信するにはSMTPHandlerを使う
import logging  ←ロガーを作成する
import logging.handlers  ←addHandlerでSMTPHandlerを指定する
...

Web

  • 辞書型をjson.dumpsに渡すことでJSON形式の文字列に変換する
  • JSON形式の文字列を辞書型にするにはjson.loadsを使う
  • JSONをファイルに書き込むにはjson.dumpを使う
  • JSONを読み込むにはjson.loadを使う(辞書型として読み込む)
import json

with open('test.json', 'w') as f:
  json.dump(j, f)

with open('test.json', 'r') as f:
  json.load(f)
import requests

payload = {'key1': 'value1'}
r = requests.get('http://~', params=payload)  ←payloadでデータを渡す

r.text  ←テキストで出力
r.json()  ←JSON形式で出力
  • Flaskの基本コード
from flask import Flask
from flask import g
from flask import render_template
from flask import request
from flask import Response


app = Flask(__name__)

# トップページ
@app.route('/')
def hello_world():
    return 'top'

# <変数>でデータを渡す
@app.route('/hello')
@app.route('/hello/<username>')
def hello_world2(username=None):
    return f'hello world!{username}'

def main():
    app.debug = True
    # サーバーの起動
    app.run()

if __name__=='__main__':
    main()
  • DBの利用
    • DBへの接続とテーブルの作成
    • GET, POST, PUT, DELETEの処理は別々に書く
    • SQLを実行するためのカーソル(curs.close())とDB接続のクローズ(@app.teardown_appcontext)
  • BeautifulSoupでタグとクラスを指定して情報を取得する(GETリクエストによるスクレイピング

並列化

  • 3つの方法
    • マルチスレッド:1つのCPUで1つのメモリを共有(作業単位であるスレッドが複数走る)
    • マルチプロセス:複数のCPUで複数のメモリを使用(作業単位であるプロセスが複数走り、データの受け渡しはプロセス間通信が必要)
    • 上記をconcurrent.fururesを使って実装:上記の切り替えが容易で単純な並列化におすすめ
  • マルチスレッド
    • スレッドに引数を渡せる
    • デーモンスレッドにより待たずに処理を進める
    • LockとRLockでスレッドの実行を制御
    • セマフォでスレッドの実行数を制御
# 基本形
import threading

def worker1():  ←worker1, 2を並列で処理
  ...

def worker2(): ←worker1, 2を並列で処理
  ...

if __name__ == '__main__':
  t1 = threading.Thread(target=worker1)  ←スレッドの作成
  t2 = threading.Thread(target=worker2)  ←スレッドの作成
  t1.start()  ←スレッドの実行
  t2.start()  ←スレッドの実行
  • マルチプロセス
    • 基本的な使い方はマルチスレッドを同じ
    • プールでプロセスの実行数を制御
    • マップでプロセスの実行数を簡単に制御
    • パイプで他のプロセスにデータを渡す
# 基本形
import multiprocessing

def worker1():  ←worker1, 2を並列で処理
  ...

def worker2(): ←worker1, 2を並列で処理
  ...

if __name__ == '__main__':
  t1 = multiprocessing.Process(target=worker1)  ←スレッドの作成
  t2 = multiprocessing.Process(target=worker2)  ←スレッドの作成
  t1.start()  ←スレッドの実行
  t2.start()  ←スレッドの実行

参考文献
酒井 潤 (著)/KADOKAWA/2022/シリコンバレー一流プログラマーが教える Pythonプロフェッショナル大全