Pythonオレオレオレオレチートシート

目次

参考ページ

https://www.python.org/

https://docs.python.org/3/

 

環境の作り方

インストール

windowsの場合

Windowsの場合,PythonのウェブサイトからインストーラーをDLする.開発するシステムに応じてバージョンを選択する.

2019年1月現在,Python3.6を推奨しているパッケージが多い印象.

Pyenvなどのバージョン管理システムもあるけど,Pythonに標準に搭載されているvenvという仮想環境構築機能で十分対応できる気がする.

とりあえずPython3.6と3.7をインストールした.インストール先のディレクトリは上書きにならないように注意(まあインストーラーが勝手にやってくれると思う)

PATHは通さなくても,Pythonのインストール先のフルパスを利用してvenvで仮想環境を作っておけば,構築以降はパスが通っているような状態になる.

 

Macの場合

これもPythonのウェブサイトからインストーラーをDLして実行するのが手っ取り早い.

 

 

Pythonの仮想環境を作る

windowsの場合

python3 -m venv ./venv
もしくは
Pythonのフルパス-m venv ./venv
これでPythonのバージョンを指定して仮想環境を作ることができる.マイナーアップデート(?)を細かく追うつもりがなければPyenvを使わなくても,venvだけで対応できそう
仮想環境を有効にするには以下のコマンドを実行する
venv\Scripts\activate.bat
ターミナルの先頭に(venv)と表示されたら仮想環境が有効な状態になっている.

Macの場合

インストーラを使ってインストールした場合,Python3.6,Python3.7それぞれ勝手にパスが通った

python3.6 -m venv ./venv
python3.7 -m venv ./venv

バージョンごとに勝手にパスを通してくれてあるのでフルパスまでは指定する必要がない.

 

仮想環境を有効にするには以下のコマンドを実行する

source venv/bin/activate
ターミナルの先頭に(venv)と表示されたら仮想環境が有効な状態になっている.

 

パッケージをDL

グローバルな環境を汚さないために,仮想環境(venv)を作って,有効にした状態で行う.

Pythonのパッケージのインストールはpipを利用する.

pip --version
pip3 --version

Python3系の仮想環境を有効にしている場合.pipもpip3も同じ動作をするっぽい.(?)

まずpipをアップデートする

pip install --upgrade pip

2019/1現在,インストールされるのはv18.1だった.

Windowsの場合,以下のコマンドを実行するように表示されるかもしれない.
python -m pip install --upgrade pip

パッケージをインストールする場合

pip install package-name

みたいなコマンドを実行する.

Successfully installedと表示されたらインストール成功.

有効にしている環境にインストールされているパッケージを一覧表示する場合,下記のコマンドを実行する

pip freeze

有効にしている環境のパッケージの一覧を保存する(テキストファイルに書き出す)には以下のコマンドを実行する
pip freeze > requirements.txt
出力された一覧のテキストを元にパッケージをインストールする場合以下のコマンドを実行する
pip install -r requirements.txt
一覧のテキストをgitの管理下に置くことで,プロジェクトをcloneしたときも同じパッケージをDLできる

 

VScodeでインテリセンスを利かす

  1. PythonのEXTENTIONをインストールする
  2. Ctrl(command)+Shift+pでコマンドパレットを表示.「Pythonのインタプリターを選択」的な項目を選択
  3. 開発に利用する仮想環境(たぶんvenvって付いてる)を選択.
  4. もし,インタプリター選択の項目に,作成した仮想環境(venv)がなければVscodeのSettingを編集する(もしくは仮想環境を設定に合わせる).
  5. VScodeのターミナルを開きなおして,仮想環境が自動で有効になればインタープリタが有効になっている.
  6. Pythonが記述されているファイルを開くと,Pylintをインストールするか聞かれる.
  7. 仮想環境が有効の状態でインストールを実行すると,インストール先が仮想環境になる.(?w)
  8. Pythonコードにインテリセンスが効く
  9. デバッグはなんか頑張ってやろう(DjangoやFlaskなどを使わない場合,初期状態のlaunch.jsonだとエラーになるので注意)

独特なブロック

pythonはインデントがブロックになる
論理行(?)先頭の空白(スペースおよびタブ)を基準にブロックを計算するらしい.

PEP8によれば,インデントはスペース4つが良いらしい.

不毛な争いはしたくないのでautopep8などで自動化するのが吉

1
2
3
4
print('hoge')
if True:
    print('huga')
    print('piyo')

コメント

1
2
3
4
5
6
# コメント
# #で始まる行はコメントになる
"""
複数行のコメント
docstringもこんな感じに記述する
"""

四則演算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 和
summation = 2+2
# 差
difference = 3-3
# 積
product = 4*4
# 商
quotient = 17/3
# 小数点を切り捨てた商
division_quotient = 17//3
# 余り
remainder = 17 % 3
# 乗算
multiplication = 5**2

イテレーション

文字列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
'シングルクオーテーション'
"ダブルクオーテーション"
 
# シングルでもダブルでも動作に違いはないらしい
 
# エスケープは\
'\'シングルクオーテーション\''
"\"ダブルクオーテーション\""
 
# rを付けると特殊文字を文字列として表示できる
r'C:\some\name'
 
"""\
複数行の文字列
改行文字は自動的に含まれる
文末に\で改行しないようにする\
らしい
"""
# 複数行の文字列
# 改行文字は自動的に含まれる
# 文末に\で改行しないようにするらしい
 
# +演算子で結合*演算子で反復できるらしい
"キラ" * 2 + "デイズ"
 
text = (
    '並んでいる文字リテラルは'
    '自動で結合される'
)
name = '星宮いちご'
# インデックスを指定して配列のように扱うことができる
# こういう要素をシーケンス (sequence) 型というみたい
name[0]  # '星'
 
name[4]  # 'ご'
 
name[0:2]  # '星宮'
name[:2]  # [0:2]と同じこと
 
name[2:5]  # 'いちご'
name[2:]  # [2:5]と同じこと※長さが5であれば
 
name[:2] + name[2:]  # '星宮いちご'
name[0:2] + name[2:5]  # '星宮いちご'
name[0:2] + name[-3:]  # '星宮いちご'
 
# 不変 (immutable) なので代入はできない
# name[0] = "月" #エラー
 
# 文字列の長さを取得する
len(name)  # 5

リスト(list)

配列といっても種類があるっぽい.(リスト,タルプ,辞書)
リストを定義するにはコンマ区切りの要素を角括弧で囲む.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
squares = [1, 4, 9, 16, 25]
# シーケンス型なのでインデックスを元に操作できる
squares[0]  # 1
squares[1]  # 4
squares[-3:]  # [9, 16, 25]
squares + [36, 49, 64, 81, 100]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
 
# リストは可変 (mutable) 型なので,要素を入れ替えられる
cubes = [1, 8, 27, 65, 125]
cubes[3] = 64  # [1, 8, 27, 64, 125]
 
# 末尾に要素を追加
cubes.append(216)  # [1, 8, 27, 64, 125, 216]
cubes.append(7 ** 3)  # [1, 8, 27, 64, 125, 216, 343]
 
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
letters[2:5] = ['C', 'D', 'E']  # ['a', 'b', 'C', 'D', 'E', 'f', 'g']
 
letters[2:5] = []  # ['a', 'b', 'f', 'g']
letters[:] = []  # []
 
# 長さを取得
letters = ['a', 'b', 'c', 'd']
len(letters)  # 4
 
 
# リストの入れ子
a = ['a', 'b', 'c']
n = [1, 2, 3]
x = [a, n]
x  # [['a', 'b', 'c'], [1, 2, 3]]
x[0]  # ['a', 'b', 'c']
x[0][1]  # 'b'

制御文

if文

switch文はないのでelifで代用する.
Pythonでは書き方を統一することで可読性を維持することができる(そうでもない気もする)

1
2
3
4
5
6
7
8
9
10
x = int(input("Please enter an integer: "))
if x < 0:
    x = 0
    print('0以下は0にするお')
elif x == 0:
    print('ゼロだお')
elif x == 1:
    print('イチだお')
else:
    print('なにか')

for文

1
2
3
idols = ['藤原 みやび', '栗栖 ここね', '堂島 ニーナ']
for idol in idols:
    print(idol, len(idol))

ループ内で要素の値を変更したりする場合
コピーを作って処理しなければ意図した動作にならばい場合がある

1
2
3
4
idols = ['藤原 みやび', '栗栖 ここね', '堂島 ニーナ']
for idol in idols[:]:
    if idol == '堂島 ニーナ':
        idols.insert(0, idol)

コピーを作成せずに実行した場合
‘堂島 ニーナ’が無限に追加される無限ループになってしまう

range()関数

1
2
3
4
5
for i in range(5):
    print(i)
range(5, 10)  # 5から10
range(0, 10, 3)  # 0から10を3刻み
range(-10, -100, -30)  # -10から-100を-30刻み

range()関数はループ処理でインデックスを利用するのに使える

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
musics = [
    "Signalize!",
    "ダイヤモンドハッピー",
    "KIRA☆Power",
    "SHINING LINE*",
    "Du-Du-Wa DO IT!!",
    "Lovely Party Collection",
    "START DASH SENSATION",
]
for index in range(len(musics)):
    print(index, musics[index])
"""
0 Signalize!
1 ダイヤモンドハッピー
2 KIRA☆Power
3 SHINING LINE*
4 Du-Du-Wa DO IT!!
5 Lovely Party Collection
6 START DASH SENSATION
"""

インデックスをつけたい場合enumerate()関数を使ったほうがいいのかも知れない

1
2
3
4
5
6
7
8
9
10
11
12
13
14
musics_with_index = list(enumerate(musics))
musics_with_index = list(enumerate(musics, start=1))
 
for music in list(enumerate(musics, start=1)):
    print(music[0], music[1])
"""
1 Signalize!
2 ダイヤモンドハッピー
3 KIRA☆Power
4 SHINING LINE*
5 Du-Du-Wa DO IT!!
6 Lovely Party Collection
7 START DASH SENSATION
"""

break文, countinue文, else節

1
2
3
4
5
6
7
8
for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print(n, 'equals', x, '*', n//x)
            break  # 最も内側のループを終了する
    else:
        # breakで終了しなければ実行される
        print(n, 'is a prime number')

continue文

1
2
3
4
5
for num in range(2, 10):
    if num % 2 == 0:
        print("Found an even number", num)
        continue
    print("Found a number", num)

pass文

何もしない

1
2
3
4
5
class MyEmptyClass:
    pass
 
def initlog(*args):
    pass

仮のクラスや関数を定義するときに,一時的に記述しておく?

関数定義

普通に

1
2
3
4
5
6
7
def fib(n):
    """Print a Fibonacci series up to n."""
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()

フェボナッチ数列を書き出す関数
return文の無い関数も,値Noneを返している

return文

値を返す場合return文を記述する

1
2
3
4
5
6
7
8
def fib2(n):  # return Fibonacci series up to n
    """Return a list containing the Fibonacci series up to n."""
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)    # see below
        a, b = b, a+b
    return result

関数内の変数スコープ

関数の変数スコープに注意

1
2
3
4
5
6
7
8
9
10
11
12
13
global_num = 2
 
def fun1():
    global_num = 1  # 関数内のスコープ
    print(global_num)
 
def fun2():
    global global_num  # 関数外(グローバルな)スコープの変数を優先する
    print(global_num)
 
fun1()  # 1
fun2()  # 2
print(global_num)  # 2

可変数の引数を取る関数の定義

デフォルトの引数値

デフォルト値が設定されている引数は,値を渡さなくてもOK

1
2
3
4
5
6
7
8
9
10
def fun3(message, is_important=False)->str:
    if is_important:
        print("\""+message+"\"")
    else:
        print(message)
 
 
fun3("こんにちは")  # こんにちは
fun3("こんにちは", True)  # "こんにちは"
fun3("こんにちは")
キーワード引数

関数に引数を渡すとき,引数名を指定して渡すことができる

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def fun4(hoge, huga="huga", piyo="piyo"):
    print("hoge:", hoge)
    print("huga:", huga)
    print("piyo:", piyo)
 
 
fun4("hoge")
"""
hoge: hoge
huga: huga
piyo: piyo
"""
 
fun4("hoge", piyo="piyo change")
"""
hoge: hoge
huga: huga
piyo: piyo change
"""
可変長引数

*nameは無限の引数,このpythonのタプル (tuple) 型によって動作している?らしい
**nameは引数名をインデックスとした辞書(dict)扱いになる
*nameは**nameより前になければいけない

引数名としては,*args, **kwargsが使われることが多い感じがする

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def fun5(name, *serifs, **statuses):
    print(name)
    for serif in serifs:
        print("「", serif, "」")
    for label in statuses:
        print(label, ":", statuses[label])
 
 
fun5("星宮 いちご", "フフッヒ", "アイカツ!", age=17, height=156)
"""
星宮 いちご
「 フフッヒ 」
「 アイカツ! 」
age : 17
height : 156
"""
fun5("霧矢 あおい", "穏やかじゃない", "アイカツ!", age=17, height=157)
"""
霧矢 あおい
「 穏やかじゃない 」
「 アイカツ! 」
age : 17
height : 157
"""
引数リストのアンパック

可変長引数の関数(range()とか)にリストやタルプで値を渡したい場合
変数に*演算子をつけるらしい

1
2
args = [3, 6]
list(range(*args))

Pythonは可変長引数の定義方法が多様なので,ちゃんと把握してないと訳が分からなくなりそう

ラムダ式

無名関数をワンラインで定義する

1
2
3
4
5
lambda a, b: a+b
 
pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
pairs.sort(key=lambda pair: pair[1])
pairs

引数として関数を受け取る関数などにワンラインで記述できる.

ドキュメンテーション文字列

関数やクラスの説明をするドキュメントdocstingとも言うらしい
アノテーションも同時に試してみる

1
2
3
4
5
6
7
8
def ab_sum(a:int, b:int)->int:
    """Sum a and b
 
    Use the operator rather than this function
    """
    return a+b
print(ab_sum.__doc__)
print(ab_sum.__annotations__)

アノテーションの役割を考えると,ドキュメントにパラメータを説明する記述するための決まりは作られていないっぽい?
とはいえアノテーションは必須な訳ではないので,あまり見かけない気がする.
ドキュメントがしっかりしていればアノテーションはいらない感もある

データ構造

リスト型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
items =["いちご", "あおい", "蘭", "おとめ", "ユリカ"]
 
items.count("あおい")
# 1
 
items.count('さくら')
# 0
 
items.index('おとめ')
# 3
 
items.reverse()
# ['ユリカ', 'おとめ', '蘭', 'あおい', 'いちご']
 
items.append('かえで')
# ['ユリカ', 'おとめ', '蘭', 'あおい', 'いちご', 'かえで']
 
items.insert(items.index('おとめ')+1, "さくら")
# ['ユリカ', 'おとめ', 'さくら', '蘭', 'あおい', 'いちご', 'かえで']
 
items.remove('いちご')
# ['ユリカ', 'おとめ', 'さくら', '蘭', 'あおい', 'かえで']
 
items.sort()
# ['あおい', 'おとめ', 'かえで', 'さくら', 'ユリカ', '蘭']
 
items.pop()
# '蘭'
 
new_items = items.copy()
# new_items = items[:] #これでも同じこと
 
items.clear()
# del items[:] #これでも同じこと

スタック

LIFO(後入れ先出し)の実装

1
2
3
4
5
6
7
8
9
10
11
stack = [3,4,5]
stack.append(6)
stack.append(7)
stack.pop()
# 7
stack.pop()
# 6
stack.pop()
# 5
stack
# [3, 4]

キュー(queue)

FIFO(先入れ先出し)の実装
標準ライブラリを使うと楽

1
2
3
4
5
6
7
8
9
10
from collections import deque
 
queue = deque([3,4,5])
queue.append(6)
queue.append(7)
queue.popleft()
# 3
queue.popleft()
# 4
queue

リストの内包表記

関数の実行結果やfor文などをもとにリストを生成する処理のこと?
appendに式を与えて平方のリストを作る

1
2
3
4
squares = []
for x in range(10):
    squares.append(x**2)
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

これだとforで使う変数xは処理後も存在し続ける(メモリのムダ使い❤️)

同じ処理を副作用なく書くにはこうする

1
2
squares = list(map(lambda x: x**2, range(10)))
squares = [x**2 for x in range(10)]

内包表記は,式,for句,if句で構成する.
ワンラインで記述されていれば入れ子など,なんでもござれ

1
2
[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
# [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

(x, y)はタルプだけど,こういう場合()が必要らしい

ネストしたリストの内包表記

1
2
3
4
5
6
# 行と列を入れ替える(違う気もするんだけど…)
[[row[i] for row in matrix] for i in range(4)]
# [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
 
list(zip(*matrix))
# [(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]

実際は複雑なことをするよりzip関数を使うなど,なるべく可読性よくした方が良さげ.
関数zipは引数をタルプで受け付けるので,*でリストをタルプとして渡している.

del文

リストの要素を削除する

1
2
3
4
5
6
7
8
9
10
11
12
13
a = ['hoge', 'huga', 'piyo', 'foo', 'bar', 'baz']
 
del a[0]
# ['huga', 'piyo', 'foo', 'bar', 'baz']
 
del a[2:4]
# ['huga', 'piyo', 'baz']
 
del a[:]
# []
 
del a
# 空のリストですらなくなって消える

タプルとシーケンス

リストは変更可能 (mutable) に対して,タプルは不変型 (immutable).
つまり値の再代入はエラーになる
複数の型の要素からなることもあるらしい.(リストもでは?)

1
2
3
4
5
6
7
8
9
10
11
12
t = 123,456, 'hoge'
t[0] #123
t # (123, 456, 'hoge')
 
u = t, (1, 2, 3, 4, 5)
# ((123, 456, 'hoge'), (1, 2, 3, 4, 5))
 
empty_tupl = () #空のタプル
singleton = 'hello', # 要素1つのタプル
 
x, y, z = t
# タプルを変数に展開(?)する.リストでも同じことはできるんだよ

値をコンマ区切りで記述する,値を囲む()は,必要な場合と不要な場合がある.
(じゃあ常に記述した方が分かりやすい気がするけど)

集合型

集合 (set) を扱うためのデータ型(らしい)
重複する要素を持たない(同じ値を追加しても要素は増えない)
順序が存在しない(順序が意味を持つデータを入れない)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
empty_set = set() # = {}ではない(辞書扱いになるらしい)
 
idols = {"あかり","スミレ","ひなき","珠璃"}
# idols = set(["あかり","スミレ","ひなき","珠璃"]) #これも同じ
print(idols)
# {'珠璃', 'ひなき', 'あかり', 'スミレ'}
 
'スミレ' in idols
# True
 
'凛' in idols
# False
 
a = set("大空あかり")
a # {'大', 'り', 'か', '空', 'あ'}

文字列はiterableなので関数set()に渡すことでset化することができる
setの内容は,要素の順番に意味が無いものになる.
人の名前など,順番に意味があるものには,あまり利用しない.

setに対して一部演算子を利用可能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
a = set("abcd")
b = set("dcef")
 
a-b # 差
# {'a', 'b'}
a|b # 和,みたいな?
# {'d', 'c', 'e', 'f', 'a', 'b'}
a&b # and
# {'d', 'c'}
a^b # not and(?)
# {'a', 'e', 'f', 'b'}
 
{x for x in 'abcde' if x not in 'abc'}
# {'d', 'e'}

辞書型 (dictionary)

dict型.連想配列的なものらしい.
キー(key): 値(value) のペアの集合
{}で囲む.仕様はタプルに近い?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
idol_heights = {"黒沢 凛": 156, "天羽 まどか": 152, "大地 のの": 156, "俺": 169}
 
idol_heights['黒沢 凛']
# 156
 
del idol_heights["俺"]
idol_heights["白樺 リサ"] = 160
# {'黒沢 凛': 156, '天羽 まどか': 152, '大地 のの': 156, '白樺 リサ': 160}
 
list(idol_heights) # 値のみをリストで取り出す
# ['黒沢 凛', '天羽 まどか', '大地 のの', '白樺 リサ']
 
sorted(idol_heights) # 値のみをソートしてリストに取り出す
# ['大地 のの', '天羽 まどか', '白樺 リサ', '黒沢 凛']
 
"白樺 リサ" in idol_heights # True
 
"俺" in idol_heights # False(俺はアイドルではない)

dict関数で,配列やタルプをdictに変換できる

1
2
3
4
5
6
7
8
9
# dict([['sape', 4139], ['guido', 4127], ['jack', 4098]])
dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
# {'sape': 4139, 'guido': 4127, 'jack': 4098}
 
{x: x**2 for x in (2, 4, 6)} # 内包表記も使える
# {2: 4, 4: 16, 6: 36}
 
dict(sape=4139, guido=4127, jack=4098) # dict関数はこういう引数の渡し方もできる
# {'sape': 4139, 'guido': 4127, 'jack': 4098}

ループテクニック

dict.items()メソッドで辞書の要素を取り出す.

1
2
3
4
5
6
7
idol_heights = {"黒沢 凛": 156, "天羽 まどか": 152, "大地 のの": 156, "白樺 リサ": 160}
for idol, height in idol_heights.items():
    print(idol, height)
# 黒沢 凛 156
# 天羽 まどか 152
# 大地 のの 156
# 白樺 リサ 160

enumerate()関数でリストにインデックスをつける

1
2
3
4
for i, v in enumerate(['hoge', 'huga', 'piyo']):
    print(i, v)
# 1 huga
# 2 piyo

クラス定義

クラスを定義する.

1
2
3
4
5
6
class MyClass:
    """A simple example class"""
    i = 12345
 
    def f(self):
        return 'hello world'

インスタンス化

1
m = MyClass()

コンストラクタ

1
2
3
4
5
6
7
8
class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart
 
 
x = Complex(3.0, -4.5)
x.r, x.i

複数のインスタンスを生成する.
インスタンスごとにスコープができることがわかる.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Dog:
 
    kind = 'canine'         # class variable shared by all instances
 
    def __init__(self, name):
        self.name = name    # instance variable unique to each instance
 
 
d = Dog('Fibo')
e = Dog('Buddy')
e.kind
d.name
e.name

リストのプロパティ,appendをラッピングしたメソッドを定義すると利用しやすい.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Dog2:
 
    def __init__(self, name):
        self.name = name
        self.tricks = []    # creates a new empty list for each dog
 
    def add_trick(self, trick):
        self.tricks.append(trick)
 
d = Dog2('Fido')
e = Dog2('Buddy')
d.add_trick('roll over')
e.add_trick('play dead')
d.tricks                # unexpectedly shared by all dogs

こういうこともできるけどメリットはなし

1
2
3
4
5
6
7
8
9
10
def f1(self, x, y):
    return min(x, x+y)
 
class C:
    f = f1
 
    def g(self):
        return 'hello world'
 
    h = g

グローバルなスコープの関数をクラスのメソッドとして定義する.

継承

1
2
3
4
5
6
7
8
9
class BaseClassName():
    pass
 
class DerivedClassName(BaseClassName):
    pass
 
# 規定クラスは式でも記述できる
class DerivedClassName(modname.BaseClassName):
    pass

インスタンスの型を調べる

1
2
obj = 1
isinstance(obj, int)

継承関係を調べる

1
2
boll_obj = True
issubclass(bool, int)

多重継承

左から優先される(深さ優先)

1
2
3
4
5
6
7
8
class Base1():
    pass
class Base2():
    pass
class Base3():
    pass
class DerivedClassName2(Base1, Base2, Base3):
    pass

プライベート変数

Pythonにはprivateなプロパティは作れない(?)
変数に_(アンダーバー)をつけるなどのコーディング規約でもって対応する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Mapping:
    def __init__(self, iterable):
        self.items_list=[]
        self.__update(iterable)
 
    def update(self, iterable):
        for item in iterable:
            self.items_list.append(item)
 
    __update = update
 
class MappingSubclass(Mapping):
 
    def update(self, keys, values):
        for item in zip(keys, values):
            self.items_list.append(item)

空のクラスを定義して構造体のような使い方もできる.

1
2
3
4
5
6
7
class Employee:
    pass
 
john = Employee()
john.name = "john Doe"
john.dept = 'computer lab'
john.salary = 1000

あまり,使う場面は思い浮かばない

イテレータ (iterator)

分かりやすく言えばforでループできるオブジェクト

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Reverse:
    """Iterator for looping over a sequence backwards."""
    def __init__(self, data):
        self.data = data
        self.index = len(data)
 
    def __iter__(self):
        return self
 
    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]

ジェネレータ (generator)

1
2
3
4
5
6
def reverse(data):
    for index in range(len(data)-1, -1, -1):
        yield data[index]
 
for char in reverse('golf'):
    print(char)

クラスメソッド@classmethod

1
2
3
4
5
class classmethodSample:
 
    @classmethod
    def f(cls, arg1, arg2):
        pass

プロパティ(property)

プロパティ(getter,setter)の定義は自力でもできる.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class PropertySample:
    def __init__(self):
        self._x = None
 
    def getx(self):
        return self._x
 
    def setx(self, value):
        self._x = value
 
    def delx(self):
        del self._x
 
    x = property(getx, setx, delx, "I'm the 'x' property.")
 
p = PropertySample()
p.x = "PropertySample.x"
print(p.x)

より良い方法としては
以下のようにデコレーターを利用すれば,インターフェースとして扱いやすい.
また,同じ関数名で定義することができる.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class PropertySample2:
    def __init__(self):
        self._x = None
 
    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x
 
    @x.setter
    def x(self, value):
        self._x = value
 
    @x.deleter
    def x(self):
        del self._x
 
p2 = PropertySample2()
p2.x = "PropertySample2"
print(p2.x)

静的メソッド(static method)

static(静的)メソッド.selfが不要.
インスタンス化しなくても実行できる.

1
2
3
4
5
6
7
class staticSample:
    @staticmethod
    def f():
        return "static method"
 
print(staticSample.f())
print(staticSample().f())

こういう書き方もできる.(するとは言ってない)

1
2
3
4
5
6
def f():
    return "static method2"
class staticSample2:
    sf = staticmethod(f)
 
print(staticSample2.sf())

supuer()メソッド:親クラスの参照

親クラスのオーバーライドしたメソッドにアクセスできる

1
2
3
4
5
6
7
8
9
10
class SuperSample():
    def method(self):
        print('SuperSample.method')
 
class SuperMethodSample(SuperSample):
    def method(self):
        super().method()
 
sms = SuperMethodSample()
sms.method()

デコレーター(decorator)

関数に関数を渡して機能を拡張する,的な
https://docs.python.org/ja/3/glossary.html#term-decorator

例外処理

1
2
3
4
5
6
while True:
    try:
        x = int(input("Please enter a number: "))
        break
    except ValueError:
        print("Oops!  That was no valid number.  Try again")

例外クラスを定義する

例外クラスを定義するにはExceptionクラスを継承する
raise句で例外を発生させる(raise=上げる)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class B(Exception):
    pass
 
class C(B):
    pass
 
class D(C):
    pass
 
for cls in [B, C, D]:
    try:
        raise cls()
    except D:
        print("D")
    except C:
        print("C")
    except B:
        print("B")
1
2
3
4
5
6
7
8
9
10
11
12
try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except OSError as err:
    print("OS error: {0}".format(err))
except ValueError:
    print("Could not convert data to an integer.")
except:
    # 空のexceptの記述は最後でなければいけない
    print("Unexpected error:", sys.exc_info()[0])
    raise

else

1
2
3
4
5
6
7
8
for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except OSError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()

例外発生時に複数の値を渡す

1
2
3
4
5
6
7
8
9
10
try:
    raise Exception('spam', 'eggs')
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst.args)     # arguments stored in .args
    print(inst)          # __str__ allows args to be printed directly,
                         # but may be overridden in exception subclasses
    x, y = inst.args     # unpack args
    print('x =', x)
    print('y =', y)
1
2
3
4
5
6
7
def this_fails():
    x = 1/0
 
try:
    this_fails()
except ZeroDivisionError as err:
    print('Handling run-time error:', err)

finally

エラーの発生に関わらず必ず実行される処理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
try:
    raise KeyboardInterrupt
finally:
    print('Goodbye, world!')
 
 
def divide(x, y):
    try:
        result = x / y
    except ZeroDivisionError:
        print("division by zero!")
    else:
        # 例外が発生しなかった場合実行される
        print("result is", result)
    finally:
        # 例外が発生しようがしまいがtryで囲まれた処理の後に必ず実行される
        print("executing finally clause")
 
divide(2, 1)
 
divide(2, 0)
 
divide("2", "1")

参考文献

Pythonプロフェッショナルプログラミング 第3版

新品価格
¥3,024から
(2019/1/6 20:41時点)

Pythonの一般的な開発環境の準備の仕方からCI,デプロイまで解説されている.
プログラミングの仕方はドキュメントで十分だったりするけど,「それで,これはどう使えばいいの?」となったときに役立つ本.

ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装

新品価格
¥3,672から
(2019/1/6 22:28時点)

Spread the love
コメントはまだありません

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

PHP
PHP俺チートシート

PHPをコーディングする上で「これどうやんだっけ」みたいのをいちいちドキュメント確認とかしてたので, …

Spread the love
Laravel
やる、Laravel5.7を。その2「インストールして認証とかを試す」

お疲れ様です. RainGearの杏です.   目次0.1 はじめに0.2 環境0.3 イ …

Spread the love
Laravel
やる,Laravelを.Homesteadで開発環境をつくる

お疲れ様です。 Raingearの杏です。 今回はPHPのフレームワークのLaravelを使ってみた …

Spread the love