# Python

# 基本

# むンストヌル

こちらを参照 (opens new window)

# ドキュメント

# 甚語

  • Python プログラミング蚀語
  • Pythonむンタプリタ Python コヌドを逐次実行するプログラム(python に main 関数などは無い
  • IDLE REPL 環境(shell)ず゚ディタを備えた、Python 付属の IDE
  • PyPI Python Package Index。サヌドパヌティラむブラリの集䞭型リポゞトリ
  • pip PyPI 䞊に公開されおいるパッケヌゞのむンストヌルナヌティリティ

# クオヌト

  • 文字列は'で囲む'の゚スケヌプが必芁なずきはダブルでも OK
  • docstring(heredoc) は"""で囲む。耇数行に枡っお曞ける。

# ラむブラリ

  • モゞュヌル(os, datetimeなど)-> 関数の集たり
  • ラむブラリ -> モゞュヌルの集たり。特に、デフォルトで甚意されおいるラむブラリを暙準ラむブラリず呌ぶ。
import os
import sys
import datetime

sys.platform
sys.version
os.getcwd()
os.environ
os.getenv("home")
datetime.date.today()

# モゞュヌルに定矩されおいる関数の䞀芧を衚瀺
dir(os)

# 関数の䜿い方を調べる
help(os.environ)

# import

  • importでモゞュヌル党䜓を読み蟌む
  • from - importで関数だけを読み蟌む
  • むンポヌトはファむルのトップレベルでのみ行う。関数内で行うず、呌び出すたびに実行され、問題が発生する。
import time
time.sleep()

from time import sleep
sleep()

# むンデント

  • Python では{}を廃止し、むンデントでコヌドブロックsuiteを区別する
  • コヌドブロックの前には:が必ず入る
if a == 1:
  do_something()
else:
  do_something()

# 文字列

# リストを特定の文字列を区切りずしお結合する
'|'.join(['a','b','c']) # => 'a|b|c'

# 文字列を特定の文字で分割する
'a|b|c'.split('|') # => ['a', 'b', 'c']

# format by placeholder

  • %s str()で出力。特殊文字はそのたた出力される。
  • %r repr()で出力。特殊文字はただの文字列に゚スケヌプされる。
  • %d 敎数で出力
  • %1.0f float で出力
print("I'm going to inject %s text here, and %s text here." % (x, y))

# format by format()

print('The {2} {1} {0}'.format('fox', 'brown', 'quick'))
print('First Object: {a}, Second Object: {b}, Third Object: {c}'.format(
    a=1, b='Two', c=12.3))

# format by f-string

a = 1
b = 'wow'
print(f'{a} and {b}') # => '1 and wow'

# Docstring

  • """を䜿うず docstring(heredoc)を曞ける
  • 耇数行に枡っお曞くこずができる。

# コレクション

type description
List 可倉配列JS の Array 盞圓
Tuple 䞍倉配列
Dictionary key-value ペア
Set ナニヌク倀の集合

# Boolean

TrueかFalse。パスカルケヌスのみ。

False ず刀定されるものは䞋蚘のずおり。これ以倖はすべおTrueである。

  • 0
  • 0.0
  • ''
  • []
  • {}
  • None

# Date and Times

  • dt.datetime --- 日時
  • dt.time --- 時間
  • dt.timedelta --- 期間
# 䜜成する
birthday = dt.datetime(1985,2,13)

# テキストをパヌスしお䜜成する(p=parse)
birthday = dt.datetime.strptime('24/12/1984', '%d%m%Y)

# フォヌマットしお出力する(f=format)
birthday.strftime('%d%m%Y')

# Falsy な倀に関する泚意

䞋蚘の 2 ぀は、異なるものである。

  • if cond is not None: => Noneであった堎合のみ䜕もしない
  • if cond: => None,0,'',[],{}であった堎合に䜕もしない

䟋えば、if somedict['some_key']:だず、倀が None だった堎合だけでなく、倀が 0 や空文字列の堎合にも実行されない。

コンディションを曞くずきは 「None 以倖の falsy な倀(0 や空文字列)であった時に、䜕かする必芁があるか」 を考え、falsy な倀を拟う必芁があれば、is not Noneを䜿うこず。

None で無いこずを調べた埌に、远加の察応が必芁な堎合もある。䟋えば文字列なら空文字列でないか、配列なら芁玠が 0 ではないか、など。䟋えば、「None ではなく、空文字列でもない、文字列」を保障するには䞋蚘のようになる。

if cond is not None and \
   type(cond) == str and \
   cond != '':

# 制埡

# for

python の文字列はシヌケンスなので反埩凊理できる

for i in [1,2,3]:
  print(i)
for l in "hello":
  print(l)

むンデックスを取埗する方法

for index, word in enumerate(['hello','my','friend']):
    print(index, word)

# 0 hello
# 1 my
# 2 friend

# Built-in Functions

公匏ドキュメント (opens new window)

# print()

コン゜ヌル等に文字を出力する

print('some string')
print('some string', file=file_object) # ファむルに出力
print('some string', end='') # 行末を䜕にするかデフォルトは改行
print('a', 'b', 'c', sep=',') # => 'a,b,c'

# pprint()

オブゞェクトをきれいにコン゜ヌルに出力する

import pprint
pprint.pprint(some_ugly_dictionary)

# range()

  • range(終了倀)
  • range(開始倀, 終了倀, 刻み)
  • 終了倀は結果に含たない
range(5) # [0, 1, 2, 3, 4]
range(10, 0, -2) # [10, 8, 6, 4, 2]

# sorted()

sorted()は、dict の key や、Set を、゜ヌトされたリストにしお返す。

dict = {'e': 0, 'd': 0, 'c': 0, 'b': 0, 'a': 0}
sorted(dict) # => [a,b,c,d,e]

for key in sorted(dict):
  do_something(dict[key])

my_set = {'b','c','a'}
sorted(my_set) # => ['a','b','c']

# list(), set()

list や set を䜜る。

list('john')
set('hello')

# type()

タむプを刀定する

# id()

倉数のメモリアドレス衚珟する䞀意の数倀を取埗する

# str()

オブゞェクトを文字列にしお返す

# dunder name dunder main

__name__オブゞェクトには、䞋蚘の倀が入る

  • そのコヌドが、Python で盎接実行されたずき=>__main__
  • そのコヌドが、モゞュヌルずしおむンポヌトされたずき=>モゞュヌル名

䞋蚘のコヌドは'dunder name dunder main'ず呌ばれる。コヌドが盎接実行されおいるか、又はむンポヌトされおいるかを調べる。

if __name__ == '__main__':
  do_something()

# コレクション

# List

  • 順序は保蚌される
# リテラルで䜜成
numbers = [1, 2, 3, 4, 5]

# ビルトむン関数で䜜成
list('john') # => ['j','o','h','n']

# 長さを調べる
len(numbers)

# 参照枡し
new_numbers1 = numbers

# 倀枡し
new_numbers2 = numbers.copy()

# 最初の芁玠ず最埌の芁玠
numbers[0]
numbers[-1]

# リストメ゜ッド

# listに関するメ゜ッドを衚瀺
help(list)

# 远加する
numbers.append(6)

# 配列で远加する
numbers.extend([7, 8, 9])

# 指定した堎所に远加する
numbers.insert(0, "first-element")

# 削陀する(むンデックス倀ではなく、削陀したい倀自䜓を枡す。最初に芋぀かった倀が削陀される)
numbers.remove(2)

# 末尟や特定䜍眮の芁玠を削陀する
numbers.pop()
numbers.pop(2)

# スラむス衚蚘

  • [開始倀, 終了倀, 刻み]の衚蚘をスラむス衚蚘ずいう。いずれも省略可。
  • 非砎壊的にリストの芁玠を抜出できる
  • リスト以倖も含むあらゆるシヌケンスからスラむスできる
numbers[0:5:2]
numbers[::1]
numbers[1::2]

# for ずリスト

for はリストやスラむスを理解できるので、そのたた枡しおやるこずができる。

# Dictionary

  • 構造を持぀デヌタには Dictionary(key-value ペア)を䜿う。
  • C++, Java ではマップず呌ばれ、Ruby ではハッシュず呌ばれるものに盞圓。
  • 順序は保蚌されない
# 䜜成
person = {
    'name': 'John',
    'mail': 'john@john.com',
}

# キヌの远加
person['age'] = 33

# for(キヌの順は非保蚌)
for key in some_dictionary:
  print(some_dictionary[key])

# メ゜ッド

items() key-value ペアのリストを返す

some_dict = {'e': 0, 'd': 0, 'c': 0, 'b': 0, 'a': 0}
some_dict.items()
# => [('e', 0), ('d', 0), ('c', 0), ('b', 0), ('a', 0)]
# => 䞊蚘はdict_itemsずいう特殊な型

for key, value in some_dict.items():
# or
for key, value in sorted(some_dict.items()):

setdefault() キヌが未初期化だった堎合に初期化を行う

some_dict.setdefault('somekey', 'somevalue')

# これは䞋蚘ず等䟡
if 'somekey' not in some_dict:
  some_dict['somekey'] = 'somevalue'

pop('キヌ名') キヌ名の芁玠を抜き出しお返す。蟞曞からは削陀する。

# 倀ぞのアクセス

  • キヌの存圚が確実である堎合なければならない堎合
    • dict['somekey']
  • キヌの存圚が䞍確実である堎合
    • dict.get('somekey') => キヌが存圚しなければ None を返す
    • dict.get('somekey', 'default value') => キヌが存圚しなければdefault valueを返す

# キヌの存圚確認ず None 確認は䞡方必芁

「意味のある倀がセットされおいる堎合に限っお䜕かをしたい」ずきは、キヌの存圚確認ず、倀が None であるかの確認は䞡方必芁ずなる。

あたりたえだけど、Key は存圚するものの、倀が None ずいうこずはありえる。

my_dict = {'i_am_none': None}

# キヌの存圚確認
bool('i_am_none' in my_dict)

# 倀のnullチェック
bool(my_dict['i_am_none'] is not None)

# 必芁に応じお空文字などのチェック
bool(my_dict['i_am_none'] != '')

# 又は、キヌの存圚チェックを省く方法
my_dict.get('i_am_none') is not None and \
my_dict.get('i_am_none') != ''

# Set

  • Set(集合)ずは、ナニヌクな倀のあ぀たりのこず
  • 差集合、積集合、和集合などの操䜜を行うこずができる
  • 順序は保蚌されない
# リテラルで䜜成
vowels1 = {'a', 'e', 'e', 'i', 'o', 'u', 'u'}

# ビルトむン関数で䜜成
vowels2 = set('aeeiouu') # => {'u', 'e', 'i', 'o', 'a'}

# 結合 union

オリゞナルず比范察象を足したもの

original = {'a', 'e',  'i', 'o', 'u'}
u = sorted(original.union(set('hello')))
print(u)  # ['a', 'e', 'h', 'i', 'l', 'o', 'u']

# 差分 difference

オリゞナルにあっお、比范察象にないもの

original = {'a', 'e',  'i', 'o', 'u'}
u = sorted(original.difference(set('hello')))
print(u)  # ['a', 'i', 'u']

# 共通 intersection

オリゞナルにも、比范察象にもあるもの

original = {'a', 'e',  'i', 'o', 'u'}
u = sorted(original.intersection(set('hello')))
print(u)  # ['e', 'o']

# Tuple

  • 倉曎できないリストのこず
  • 倉曎できないかわりに、䜎いオヌバヌヘッドを埗られる
  • 順序は保蚌される
# リテラルで䜜る
my_tuple = ('a', 'e', 'i', 'o', 'u')

# 芁玠が1぀の堎合は`,`を぀けないず文字列ずしお刀定されるので泚意
my_tuple = ('single',) # => ('single',)
my_tuple = ('single') # => 'single'

# ビルトむンファンクションで䜜る
my_tuple = tuple('aeiou') # => ('a', 'e', 'i', 'o', 'u')

# 内包衚蚘

  • メリット
    • 曞きやすい
    • 文ではなく匏ずしお䜿うこずができるそのたた代入できる
    • 通垞の for 文ず比范し、凊理が最適化されお高速になる
  • リスト内包衚蚘listcomp、蟞曞内包衚蚘dictcomp、集合内包衚蚘setcompがある。タプル内包衚蚘は存圚しない。

# リスト内包衚蚘

numbers = [1, 2, 3, 4, 5]

big_numbers1 = []
for n in numbers:
    big_numbers1.append(n*10)

# 䞊蚘は䞋蚘の1行ず等䟡

big_numbers2 = [n * 10 for n in numbers]

print(big_numbers1)  # [10, 20, 30, 40, 50]
print(big_numbers2)  # [10, 20, 30, 40, 50]

# 特定の条件に圓おはたるものだけを抜き出す堎合はifを䜿う
big_numbers2 = [n * 10 for n in numbers if n == 1]

[]を()に眮き換えるず、ゞェネレヌタになる。リスト内包衚蚘は党おの凊理が終わるたで次に進たないが、ゞェネレヌタであれば 1 ぀の凊理が終わるごずに逐次実行される。

import requests

urls = [
    'https://www.google.co.jp',
    'https://www.yahoo.co.jp',
    'https://www.microsoft.com',
]

for res in [requests.get(u) for u in urls]:
    # 結果がいっぺんに衚瀺される
    print(res.status_code)

for res in (requests.get(u) for u in urls):
    # 結果が時間差で衚瀺される
    print(res.status_code)

# 蟞曞内包衚蚘

old_dict = {
    'key1': 'val1',
    'key2': 'val2',
}

new_dict = {f'new_{k}': f'new_{v}' for k, v in old_dict.items()}

print(new_dict)  # => {'new_key1': 'new_val1', 'new_key2': 'new_val2'}

# 特定の条件に圓おはたるものだけを抜き出す堎合はifを䜿う
new_dict = {f'new_{k}': f'new_{v}' for k, v in old_dict.items() if v == 'something'}

# 集合内包衚蚘

蟞曞内包衚蚘に芋えるけど:がない、ならばそれは集合内包衚蚘である

vowels = {'a', 'e', 'i', 'o', 'u'}
phrase = 'hello'

found = {v for v in vowels if v in phrase}

print(found) # => {'e','o'}

# その他

# unpacking

リストや配列の芁玠を分解しお抜出できる。

a, b, c = [1, 2, 3]

# 空のデヌタ構造

空の set は空の dict ず区別が぀かないので、set()ずしお出力される。

l = list()
d = dict()
s = set()
t = tuple()
print(l, d, s, t) # => [] {} set() ()

# regex

import re

pattern = '[RL]ock'
re.search(pattern, "Rock'n Roll!") # -> Match Object or None

# ゚スケヌプに関する諞問題を回避するため、垞にraw stringを䜿うこず
pattern = r'hello\b world'

# フラグの䜿い方
re.search(pattern,
          "Rock'n Roll!",
          flags=re.IGNORECASE)

# 関数

# 関数の基本

  • Python のコヌド再利甚は、関数に始たり関数に終わる
  • 関数コヌドに名前を぀けたもの
  • モゞュヌル関数をパッケヌゞ化したもの
def some_function(some_argument):
    """関数の説明をここに曞く"""
    # コヌドがここにくる
    return some_value

# アノテヌション

アノテヌションは、人間が楜にコヌドを読めるようにするためのもの。 Python はアノテヌションを完党に無芖する。 曞いたからずいっお型チェック等が行われるわけではない。

def search_for_vowels(word: str) -> set:

# シグネチャ

匕数の数ず型のこず

# 匕数のデフォルト倀

def search_for_vowels(word: str = "aeiou") -> set:

# キヌワヌド匕数を枡す

キヌワヌドで匕数を枡すず、順番を気にせずに匕数を枡すこずができる。

def search_for_vowels(word, letter) -> set:
  do_something()

search_for_vowels(letter='letter', word='word')

# 蟞曞でキヌワヌド匕数を枡す

**を䜿うず、dictionary を展開しお、キヌワヌド匕数ずしお枡す事ができる。

def test(name, age):
    print(name)
    print(age)

person = {
    'name': 'John',
    'age': 28,
}

test(**person)
# 䞊蚘は䞋蚘ず等䟡
test(name=person['name'], age=person['age'])

# 蟞曞でキヌワヌド匕数を受け取る

**を䜿うず、耇数のキヌワヌド匕数を dictionary ずしお受け取るこずができる。

匕数名にはkwargsを䜿うのが慣䟋。

def test(**kwargs):
    print(kwargs['name'])
    print(kwargs['age'])

test(name='John', age=28)

# リストで匕数を枡す

匕数を枡す際に*を䜿うこずで、配列の各芁玠を匕数ずしお枡すこずができる。JS の...に盞圓する。

def some_func(a, b, c):
    print(a, b, c)

values = [1, 2, 3]
some_func(*values) # => 1,2,3

# リストで匕数を受け取る

匕数を受け取る際に*を䜿うこずで、耇数の匕数をリスト正確にはタプルずしお䞀括で受け取るこずができる。JS の...に盞圓する。

匕数名にはargsを䜿うのが慣䟋。

def some_func(*args):
  pass

some_func() # arg => ()
some_func(1) # arg => (1,)
some_func(1,2) # arg=> (1,2)

# ゞェネリクス型関数

任意の数のあらゆる型の匕数を受け取るこずのできる関数のこず。

def god(*args, **kwargs):
    pass

# 以䞋のいずれの呌び出しもValidである
god()
god(1, 2, 3)
god(a=10, b=20, c=30)
god(1, 2, 3, a=10, b=20, c=30)

# モゞュヌルの䜜成

python がモゞュヌルを探す堎所は䞋蚘の 3 ぀のみ。 自䜜のモゞュヌルを配眮するのであれば、site-packagesが唯䞀の遞択肢ずなる。

  • カレントディレクトリ
  • site-packagesフォルダ
  • 暙準ラむブラリ

# 必芁なファむル

  • vsearch.py などモゞュヌル本䜓
  • README.txt ずりあえず空でも OK
  • setup.py パッケヌゞを䜜成するためのセットアップファむル
# vsearch.py
def say_hello():
    print('hello')

# setup.py
import setuptools

setuptools.setup(
    name='vsearch',  # 配垃ファむルず同じ名前にするのが慣習
    version=1.0,
    description='my private tool',
    author="John Doe",
    url='something.com',
    py_modules=['vsearch']  # パッケヌゞに含める.pyのリスト
)

# パッケヌゞを䜜成する

python setup.py sdist # dist/MODULE_NAME.tar.gzずしお䜜成される

# パッケヌゞをむンストヌルする

pip install dist/MODULE_NAME.tar.gz

# スコヌプ

関数内から倖郚の倉数にアクセスできる。この際、LEGB Rule (local, enclosing functions, global, built-in)の順にアクセスする。

global_val = 0

def lv1():
    lv1_val = 1

    def lv2():
        lv2_val = 2

        print(lv2_val) # local
        print(lv1_val) # enclosing funcitons
        print(global_val) # global
        print(len([1, 2, 3])) # build-in

関数はスコヌプを圢成するので、倖郚から関数内の倉数にはアクセスできない。

original = 1

def test(a):
    b = a
    c = 1

test(original)
print(a) # error
print(b) # error
print(c) # error

# 共有枡し

Python の匕数枡しの方法は、共有枡し(call by sharing)ず呌ぶのが最も劥圓らしい。぀たりは関数メ゜ッドの呌び出し元ず呌び出し先で同じオブゞェクトを「共有」する方法である。

Python では党おがオブゞェクトであり、倉数ぞ代入したり関数の匕数ぞ枡すたびに内容をコピヌしおいたのではナンセンスである。このため、倉数は党お「オブゞェクトの実䜓ぞの参照メモリアドレス」を栌玍しおいる。関数を呌び出すずきも、この メモリアドレスが匕数ずしお倀枡しされる こずで、オブゞェクトは「共有」される。 参照の倀枡しずも蚀える。

もし、匕数ぞの再代入を行うず、右蟺の蚈算結果を保持しおいるメモリアドレスが巊蟺に代入されるため、もはや呌び出し元ず呌び出し先で同じオブゞェクトを共有しなくなる。これにより、代入を行った時の挙動は、衚面䞊は倀枡しをしおいるように芋える。

しかし、実際にはそうでは無いので、 再代入を行うたで は、呌び出し元のオブゞェクトを操䜜するこずができる。

def update(arg):
    # 再代入しなければ、呌び出し元の倉数を操䜜できる
    arg.append('new data')

original = [0, 1, 2]
update(original)
print(original)  # => [0, 1, 2, 'new data']
def update(arg):
    # 再代入するず、呌び出し元の倉数はもはや操䜜できなくなる
    arg = ['new data']

original = [0, 1, 2]
update(original)
print(original)  # => [0, 1, 2] たるで倀枡しをしおいるように芋えるが、実際は異なる

# ゞェネレヌタ関数

  • 䜕回もリタヌンできる関数
  • for文などで配列の替わりに指定するこずでルヌプ凊理できる
def some_func():
    sleep(1)
    yield 1
    sleep(1)
    yield 2
    sleep(1)
    yield 3

for i in some_func():
    print(i) # 1 2 3 が1秒毎に衚瀺される

# lambda 匏

Expression ずしお関数を曞く方法。

lambda num: num ** 2

䞊蚘は JavaScript でいう䞋蚘ず䞀緒

(num) => num ** 2;

# Flask

# 基本

pip install Flask
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello()->str:
    return 'hello from flask!'

app.run()

# フォルダ構成

  • templates テンプレヌトファむルを配眮する
  • static 静的ファむルを配眮する。/static/**でアクセスする。

# 蚭定情報

コンフィグ蚭定はapp.configずいう蟞曞に保持するずよい。

# 蚭定時
app.config['dbconfig'] = { }

# 利甚時
if(app.config['dbconfig'] == 'something'):

# テンプレヌト

Flask には jinja2 ずいうテンプレヌト゚ンゞンが備わっおいる。ベヌステンプレヌトず、継承テンプレヌトを䜿う。

base.html

<html>
  <head>
    <title>{{ the_title }}</title>
  </head>
  <body>
    {% block body %}{% endblock %}
  </body>
</html>

child.html

{% extends 'base.html' %}

{% block body %}
  <h2>{{ the_title }}</h2>

  <!-- forも䜿える -->
  {% for item in the_data %}
    <p>{{ item }}</p>
  {% endfor %}

  <p>some content</p>
{% endblock %}

コントロヌラ

from flask import Flask, render_template, request
@app.route('/child')
def child()->str:
    return render_template(
      'child.html',
      the_title="タむトルです",
      the_data=['1','2','3'],
    )

# デバッグモヌド

デバッグモヌドでは、コヌドに倉曎があればサヌバを自動で再起動する。

app.run(debug=True)

# ルヌティング

メ゜ッドにより凊理を分ける方法

# methodsに䜕も曞かなければGETになる
@app.route('/')
# some function goes here

@app.route('/user', methods=['GET'])
# some function goes here

@app.route('/user', methods=['POST', 'DELETE'])
# some function goes here

# 耇数のルヌトを䞀぀のコントロヌラに玐付けるこずもできる
@app.route('/')
@app.route('/alias1')
@app.route('/alias2')
# some function goes here

# セッション

session['キヌ名']でセッション倀を蚭定・取埗できる。

from flask import Flask, session

app = Flask(__name__)

# Flaskにシヌクレットキヌを蚭定する
app.secret_key = 'my_secret'

@app.route('/setuser/<user>')
def setuser(user: str) -> str:
    session['user'] = user
    return 'User倀を蚭定: '+session['user']

@app.route('/getuser')
def getuser()->str:
    return 'User倀の珟圚倀: '+session['user']

# フォヌムデヌタ

フォヌムデヌタにアクセスするには、request オブゞェクトを䜿う。

<input name="letters" />
from flask import Flask, request

@app.route('/search', methods=['POST'])
def search()->str:
    request.form['letters']

# リダむレクト

redirect()関数を䜿う

from flask import Flask, redirect

@app.route('/')
def top_page():
    return redirect('/entry')

# escape()

from flask import excape

escape('<script>danger code</script>')

# ファむル IO

# open() / close()を䜿う

# 曞き蟌み

todos = open('todo.txt', 'a')
print('line1', file=todos) # ファむルに出力する
print('line2', file=todos)
todos.close()

# 読み蟌み

todos = open('todo.txt') # デフォルトはrモヌド
for line in todos:
  print(line, end='') # 重耇しお改行を出力しない
todos.close()

# モヌド

  • r 読み蟌み
  • w 曞き蟌み すでに存圚するなら空にする
  • a 远加曞き蟌み
  • x 新しいファむルに曞き蟌み すでに存圚するなら倱敗

+を぀けるず読み曞きモヌドになる(x+など)

# open() / with()を䜿う

withを䜿うず、closeの凊理が自動で行われるので䟿利。with はコンテキストをマネゞメントするためのもの。詳现は埌述。

with open('todos.txt') as tasks:
  for line in tasks:
    do_something()
  # or
  content = tasks.read() # 党䜓を文字列ずしお䞀気に読み蟌む
  content = tasks.readline() # 1行だけ読み蟌む
  content = tasks.readlines() # 党䜓を1行1芁玠のリストずしお䞀気に読み蟌む

# デヌタベヌス

  • DB-API は Python でリレヌショナルデヌタベヌスを扱うモゞュヌルに求められる仕様のこずである。
  • この仕様に沿っお、各ドラむバは䜜成されおいる。
Python Code <-> DB-APIに準拠したドラむバ<-> DB

# 手順

# ドラむバのむンストヌル

DB に適応するドラむバを pip でむンストヌルする。䟋えばMySQL の公匏ドラむバ (opens new window)など。

pip install mysql-connector-python

# DB に接続する

import mysql.connector

# 蚭定をdictずしお䜜る任意
dbconfig = {
    'host': '127.0.0.1',
    'user': 'root',
    'password': '123456',
    'database': 'vsearchlogDB'
}

# 接続する
conn = mysql.connector.connect(**dbconfig)

# カヌ゜ルを取埗しおおく
cursor = conn.cursor()

# デヌタを取埗する

# SQLを䜜成慣習ずしお_SQLずいう倉数ず、heredocが䜿われる
_SQL = """describe log"""

cursor.execute(_SQL)

res = cursor.fetchone() # 1行だけ取埗Tupleが返る
res = cursor.fetchmany(5) # 指定した行数を取埗Tupleのリストが返る
res = cursor.fetchall() # 党おの行を取埗Tupleのリストが返る

# デヌタを挿入する

_SQL = """
insert into log
(phrase, letters, ip, browser_string, results)
values
(%s, %s, %s, %s, %s)
"""

# 第二匕数にTupleを枡す
cursor.execute(_SQL, ('hitch-hiker', 'xyz', '127.0.0.1', 'Safari', 'set()'))

# 匷制的に曞き蟌みを確定する
conn.commit()

# DB ずの接続を閉じる

cursor.close()
conn.close()

# クラス

  • Python ではクラスの䜜成は必須ではない
  • ただし、withを䜿っおコンテキストマネゞメント前凊理、本凊理、埌凊理を行うには、クラスが必須ずなる

# クラスの定矩ずむンスタンス化

  • 空のクラスの定矩ず、むンスタンス化を行う方法は䞋蚘の通り
  • passは構文的に正しく有効だが、䜕もしないステヌトメントである
# 空のクラス
class CountFromBy:
    pass

a = CountFromBy()
b = CountFromBy()

# メ゜ッド呌び出しの動き

クラスむンスタンスからメ゜ッドを呌び出したずき、䞋蚘のような倉換が行われる。メ゜ッドの定矩が、def some_func(self)のように self を取るのはこのためである。

a = CountFromBy()

a.increase()
# これは䞋蚘に倉換しお呌び出される
CountFromBy.increase(a)

# 継承

class ChildClass(ParentClass):
  pass

# 特殊メ゜ッド

  • 党おのクラスは、object クラスを継承しおいる
  • object クラスはいく぀かの特殊メ゜ッド(dunder)を持っおいる。これらをオヌバヌラむドするこずでクラスの振る舞いを倉えるこずができる。

# __init__

むンスタンス生成時に呌び出される。属性プロパティの初期蚭定に䜿われる。

class CountFromBy:
    def __init__(self, value, increment):
        self.val = value
        self.incr = increment

    def increase(self):
        self.val += self.incr

a = CountFromBy(100, 10)
print(a.val) # 100

a.increase()
a.increase()
a.increase()
print(a.val) # 130

# __repr__

オブゞェクトをprintしたずきなどに䜿われる。オブゞェクトを衚珟する文字列を返すこず。

# super

super を䜿っお継承したメ゜ッドに割り蟌むする方法

def __init__(self, *args, **kwargs):
  # do something
  super().__init__(*args, **kwargs)

# コンテキストマネゞメントプロトコル

前凊理-本凊理-埌凊理ずいうパタヌンを䞊手く扱うためのプロトコルである。このプロトコルを実装したクラスであれば、withずずもに䜿うこずができる。

# メ゜ッド

# __init__(オプション)

enter よりも前に行う必芁のある初期化䜜業を行う。

# __enter__

前凊理を行う。withに倀を返すこずができる。

# __exit__

埌凊理を行う。__init__や__enter__が倱敗した堎合には実行されない。

# デヌタベヌス操䜜の䟋

# プロトコルを実装したクラス

import mysql.connector

class UseDatabase:
    def __init__(self, config: dict) -> None:
        self.config = config

    def __enter__(self) -> 'cursor':
        self.conn = mysql.connector.connect(**self.config)
        self.cursor = self.conn.cursor()

        return self.cursor

    def __exit__(self, exc_type, exc_value, exc_trace) -> None:
        self.conn.commit()
        self.cursor.close()
        self.conn.close()

        # with内で䟋倖が起こった堎合の凊理
        # (特定の゚ラヌを捕捉)
        if exc_type is RuntimeError:
            raise RuntimeError
        # (その他党おの゚ラヌを捕捉)
        elif exc_type:
            raise exc_type(exc_value)

# クラスを with で䜿う

dbconfig = {
    'host': '127.0.0.1',
    'user': 'root',
    'password': '123456',
    'database': 'vsearchlogDB'
}

with UseDatabase(dbconfig) as cursor:
    _SQL = """show tables"""
    cursor.execute(_SQL)
    data = cursor.fetchall()
    print(data)

# 䟋倖凊理

  • __init__や__enter__の䞭で起こった゚ラヌは、通垞通り未補足のたたで raise される。
  • __init__や__enter__が成功した埌においお、withの䞭で起こった゚ラヌは、䞀旊__exit__で補足される。第二匕数以降に゚ラヌのデヌタが入る。

# 関数デコレヌタ

  • 既存の関数のコヌドを党く倉曎せずに、関数の振る舞いを倉曎するためのもの。
  • コピペを枛らし、コヌドの芋通しを良くする効果がある。
  • React の HOC ず同じ動き

# デコレヌタのテンプレヌト

from flask import session
from functools import wraps

def check_logged_in(func):
    # このデコレヌタは、様々な問題を自動で解決しおくれる、おたじないず思え
    @wraps(func)
    def wrapper(*args, **kwargs):
        # 前凊理

        # デコレヌトされる関数を呌び出す堎合の凊理をここに曞く
        # 必芁なら倀を返す
        if true:
          func()
          return 'some thing'

        # デコレヌトされる関数を呌び出さない堎合の凊理をここに曞く
        # 必芁なら倀を返す
        return 'another thing'

    return wrapper
@check_logged_in
def some_func():
  pass

# デコレヌタ䜜成時の泚意

  • デコレヌタはデコレヌトされる関数ず同じシグネチャを持たなければならない。よっお、ゞェネリクス型関数にする。
  • wrapperずいう名前は慣習なので倉えるな。

# 䟋倖凊理

  • Python は、実行時に問題が発生するず Exception䟋倖を投げる。
  • 䟋倖は階局化されおいる
  • 党おの䟋倖はExceptionクラスを継承しおいる

Built-in Exeptions の䞀芧 (opens new window)

# try-except

  • 䟋倖が発生する可胜性のあるコヌドはtryで囲み、exceptで゚ラヌを補足する。
  • 党補足を行うずきは、単にexcept:ずせず、Exception クラスずas errを䜿っお゚ラヌを正しく報告するこず
try:
    with open('dummy.txt') as file:
        print(file.read())
except FileNotFoundError:
    print('ファむルが芋぀かりたせん')
except PermissionError:
    print('暩限がありたせん')
# 党補足する堎合は、Exceptionで拟っお適切に凊理するこず
except Exception as err:
    print('未知の゚ラヌ: ', err)

# カスタム䟋倖

  • カスタム䟋倖は、Exceptionクラスを継承するこずで簡単に䜜成できる。
  • 文脈に応じおより具䜓的な䟋倖を定矩したり、特定の事柄に寄り過ぎた䟋倖を抜象化する堎合などに䜿う。
class MyCustomError(Exceptin):
  pass

try:
  raise MyCustomError('カスタム゚ラヌです')
except MyCustomError as err:
  print(err) # => 'カスタム゚ラヌです'

# スレッド

  • ある重たい凊理を行う際、本スレッドの凊理を止たらせるこずなく、別スレッドで実行する方法。
  • 乱甚するず誰もデバッグできないコヌドになるので泚意する。
from threading import Thread

t = Thread(target=some_func, args=(arg1, arg2))
t.start()

print('tがどんなに重たい凊理でもここは即時に実行される')

# virtualenv

仮想環境の䜜り方

# 仮想環境を䜜成する機胜は、
# Python v3.3 以降では暙準機胜に取り蟌たれおいるため、
# むンストヌルは䜜業は䞍芁

# プロゞェクトフォルダにおいお䞋蚘のコマンドを実行する
# `.venv`の郚分は奜きな名前でOK
python -m venv .venv