よく使いそうな組み込み関数
| all |
全てが True なら True |
| any |
一つでも True なら True |
users = [
{"name": "Alice", "is_active": True},
{"name": "Bob", "is_active": False},
{"name": "Charlie", "is_active": True},
]
# 全員がアクティブかチェック
all_active = all(u["is_active"] for u in users)
# 一人でもアクティブがいるかチェック
any_active = any(u["is_active"] for u in users)
| next |
条件に合う最初の要素を取り出す |
numbers = [1, 3, 5, 8, 10, 13]
# 偶数のうち、最初のものを取得。見つからない場合は None を返す
first_even = next((x for x in numbers if x % 2 == 0), None)
| sorted |
|
| max/min |
|
data = [
{"name": "Apple", "price": 100},
{"name": "Orange", "price": 80},
{"name": "Banana", "price": 150},
]
# 価格が一番高いものを取得
expensive_item = max(data, key=lambda x: x["price"])
# 名前の長さ順にソート
sorted_by_len = sorted(data, key=lambda x: len(x["name"]))
filter や map はリスト内包表記でやるのがベター。 ただし状況によっては使った方が良いこともある。
numbers = [1, 2, 3, 4, 5, 6]
# 1. filter を使う場合 (lambdaが必要になることが多い)
evens_filter = filter(lambda x: x % 2 == 0, numbers)
# 2. リスト内包表記を使う場合
evens_list = [x for x in numbers if x % 2 == 0]
numbers = [1, 2, 3, 4, 5]
# 1. map を使う場合
squared_map = map(lambda x: x**2, numbers)
# 2. リスト内包表記を使う場合
squared_list = [x**2 for x in numbers]
Task Runner
全体を表示
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import sys
from logging import (
CRITICAL,
DEBUG,
ERROR,
INFO,
WARNING,
StreamHandler,
getLevelName,
getLogger,
)
from logging import Formatter as logFormatter
PJ_NAME = "PJ_NAME"
log_handler = StreamHandler(stream=sys.stderr)
log_handler.setLevel(DEBUG)
log_handler.setFormatter(
logFormatter(
"%(asctime)s - %(name)s - %(levelname)s - %(filename)s(%(lineno)d):%(funcName)s - %(message)s",
),
)
logger = getLogger("{}".format(PJ_NAME))
logger.setLevel(DEBUG)
logger.addHandler(log_handler)
def main(username: str):
logger.info("=== RUN! =================")
logger.info("username: [%s]", username)
logger.info("================= FINISH! ===")
if __name__ == "__main__":
args_parser = argparse.ArgumentParser(description=PJ_NAME)
args_parser.add_argument(
"-u",
"--username",
type=str,
default="username",
help="ユーザーネーム (default: username)",
)
args_parser.add_argument(
"-l",
"--log-level",
type=str,
choices=[
getLevelName(CRITICAL),
getLevelName(ERROR),
getLevelName(WARNING),
getLevelName(INFO),
getLevelName(DEBUG),
],
default=getLevelName(INFO),
help="ログレベル (default: INFO)",
)
args = args_parser.parse_args()
logger.setLevel(args.log_level)
if args.log_level != getLevelName(DEBUG) or input("実行するなら y を入力: ") == "y":
main(args.username)
else:
logger.info("キャンセル")
sys.exit(0)
for 文
# range を使う (start, stop, step)
for i in range(0, 3, 1):
print(i)
# 0
# 1
# 2
# 配列を処理
items = ['a', 'b', 'c']
for item in items:
print(item)
# a
# b
# c
# 辞書のループ
# items 以外にも keys や values がある
d = {'a': 1, 'b': 2, 'c': 3}
for key, value in d.items():
print(key, value)
# a 1
# b 2
# c 3
odds = [i for i in range(10) if i % 2 == 1]
print(odds)
for i in range(0, 3, 1):
print(i)
else:
# 最後まで実行された場合に処理
# break した場合は処理しない(たぶん例外でも処理しない)
print('Finish!')
code format
| 項目 | 値 | 備考 |
|---|---|---|
formatter |
autopep8 |
|
checker |
flake8 |
# pipenv など仮想環境の使用を推奨
pip install --dev autopep8 flake8
{
// 保存時にフォーマットを実行
"editor.formatOnSave": true,
// 文字列長の最大値チェックを120に変更
"python.linting.flake8Args": [
"--max-line-length=120",
],
// フォーマット時の文字列長の最大値を120に変更
"python.formatting.autopep8Args": [
"--max-line-length=120"
]
}
code style
キーワード引数を使うかどうか
キーワード引数 は必須ではなく、デフォルト値を持ちます。 これらは、関数に送信されるオプションのパラメータによく使用されます。 関数に2つまたは3つ以上の位置パラメータがある場合、そのシグネチャは覚えにくいため、キーワード引数をデフォルト値で使用すると便利です。 例えば、より完全な send 関数は send(message, to, cc=None, bcc=None) として定義できます。ここで、 cc と bcc はオプションで、別の値が渡されないときは None と評価されます。
「関数に2つまたは3つ以上の位置パラメータがある場合」とあるので、3つ以上の引数がある場合はキーワード引数がよいのかも。
アスタリスク (*)
-
ref. Python3.xのアスタリスク逆引き
def useless_func(a, b, *args, c, d):
pass
useless_func(1, 2, 3, 4, 5, 6) # NG
useless_func(1, 2, 3, 4, c=5, d=6) # OK
# OK の場合は次のように割り当てられる
# a: 1
# b: 2
# args: (3, 4)
# c: 5
# d: 6
# 仮引数名ナシの場合、以降(例では c, d)はキーワード引数を強制する
def useless_func(a, b, *, c, d):
pass
useless_func(1, 2, 3, 4, c=5, d=6) # NG
useless_func(1, 2, c=5, d=6) # OK
# OK の場合は次のように割り当てられる
# a: 1
# b: 2
# c: 5
# d: 6
# ** はキーワード引数を辞書にまとめる
def useless_func(**kwargs):
print(kwargs)
useless_func(a=1, b=2, c=3)
# {'a': 1, 'b': 2, 'c': 3}
def useless_func(*args, **kwargs):
print(args, kwargs)
useless_func(1, 2, 3, a=1, b=2, c=3)
# (1, 2, 3) {'a': 1, 'b': 2, 'c': 3}
アンダーバー (_)
-
ref. pythonのアンダーバーこれなんやねん
H,W,_ = img.shape
def _single_leading_underscore(x):
return n
#weak "internal use" indicator. E.g. from M import *
#does not import objects whose names start with an underscore.
基本的に外部からの参照を受け付けない,ってものにはアンダーバーを1つつけるというのがpythonの習わしのようです。
def __double_leading_underscore:
return n
#when naming a class attribute, invokes name mangling
#(inside class FooBar, __boo becomes _FooBar__boo; see below).
外部からのアクセスを受け付けませんよ対策の1つと言えるのではないかと思います。
def list_(x):
return n
#used by convention to avoid conflicts with Python keyword
pythonの予約語をどーしても関数名に使いたい時には,後ろに1つ_つけてつかいわけろ,ということみたいです。
def __double_leading_and_trailing_underscore__:
return n
# "magic" objects or attributes that live in user-controlled
# namespaces. E.g. __init__, __import__ or __file__. Never invent
# such names; only use them as documented.``
オブジェクトの振る舞いを変更したり,クラスの性質にあった動きをさせたい時に使うものなんだそうです。
alembic
# インストール
sudo apt install libpq-dev
pipenv install psycopg2
pipenv install --dev alembic
# 初期化
alembic init
# マイグレーションファイル生成
alembic revision -m "create users table"
# マイグレーション
alembic upgrade head
alembic upgrade +2
# マイグレーション(SQLの出力。実行はしない)
alembic upgrade ae1027a6acf --sql
# ロールバック
alembic downgrade base
alembic downgrade -1
# 現在の状態
alembic current
# 履歴表示
alembic history --verbose
データ型一覧(PostgreSQL ベース)
|
一部のみ。詳細はドキュメント参照。 |
| データ型 | 指定値 | 備考 |
|---|---|---|
bigint |
sa.BIGINT(), sa.BigInteger(), sa.dialects.postgresql.BIGINT |
|
bit(1) |
sa.dialects.postgresql.BIT |
|
boolean |
sa.BOOLEAN(), sa.Boolean(), sa.dialects.postgresql.BOOLEAN |
|
bytea |
sa.Binary(), sa.LargeBinary(), sa.PickleType(), sa.dialects.postgresql.BYTEA |
|
character varying |
sa.String(), sa.Unicode(), sa.VARCHAR(), sa.dialects.postgresql.VARCHAR |
character varyingが長さ指定なしで使われた時は、いかなる長さの文字列でも受け付けます。(PostgreSQLの拡張) |
character varying(256) |
sa.String(256), sa.VARCHAR(256) |
|
character varying[] |
sa.ARRAY(sa.String()) |
|
character(1) |
sa.CHAR(), sa.NCHAR(), sa.dialects.postgresql.CHAR |
|
cidr |
sa.dialects.postgresql.CIDR |
|
date |
sa.DATE(), sa.Date(), sa.dialects.postgresql.DATE |
|
double precision |
sa.FLOAT(), sa.Float(), sa.dialects.postgresql.FLOAT, sa.dialects.postgresql.DOUBLE_PRECISION |
|
inet |
sa.dialects.postgresql.INET |
|
integer |
sa.INT(), sa.INTEGER(), sa.Integer(), sa.dialects.postgresql.INTEGER |
|
integer[] |
sa.ARRAY(sa.Integer()) |
|
interval |
sa.Interval(), sa.dialects.postgresql.INTERVAL |
|
json |
sa.JSON() |
|
macaddr |
sa.dialects.postgresql.MACADDR |
|
money |
sa.dialects.postgresql.MONEY |
|
numeric |
sa.DECIMAL(), sa.NUMERIC(), sa.Numeric(), sa.dialects.postgresql.NUMERIC |
|
oid |
sa.dialects.postgresql.OID |
|
enum |
sa.Enum(ClassName, values_callable=lambda obj: [e.value for e in obj]) |
|
real |
sa.REAL(), sa.dialects.postgresql.REAL |
|
regclass |
sa.dialects.postgresql.REGCLASS |
|
smallint |
sa.SMALLINT(), sa.SmallInteger(), sa.dialects.postgresql.SMALLINT |
|
text |
sa.TEXT(), sa.Text(), sa.UnicodeText(), sa.dialects.postgresql.TEXT |
いかなる長さの文字列でも格納できるtextをサポートします。 text型は標準SQLにはありませんが、多くの他のSQLデータベース管理システムも同様にサポートしています。 |
time without time zone |
sa.TIME(), sa.Time(), sa.dialects.postgresql.TIME |
|
timestamp with time zone |
sa.DateTime(timezone=True) |
timestamp with time zoneについて内部に格納されている値は常にUTCです。 |
timestamp without time zone |
sa.DateTime(), sa.DateTime(timezone=False), sa.TIMESTAMP(), sa.dialects.postgresql.TIMESTAMP |
|
tsvector |
sa.dialects.postgresql.TSVECTOR |
|
uuid |
sa.dialects.postgresql.UUID |