Python
基本
インストール
ドキュメント
用語
Python
プログラミング言語Pythonインタプリタ
Python コードを逐次実行するプログラム(python に main 関数などは無い)IDLE
REPL 環境(shell)とエディタを備えた、Python 付属の IDEPyPI
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
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)