【全部まとめ】AI開発に必要なPython
前提
- Python実行環境
- 外部リンク: Minicondaインストール
プロンプトへの出力
これだけは覚えておく
リテラル
print(1)
print('x'+','+"y")
1 x,y
- 数値の出力ができる
- 文字列を使える
- 「’」または「"」で囲う
- 「+」で連結
変数
a=11;b=22;c='p';d='q'
print(a+b)
print(str(a)+str(b))
print(c+':'+str(a)+','+d+':'+str(b))
print(f'{c}:{a},{d}:{b}')
print('{}:{},{}:{}'.format(c,a,d,b))
print('{p}:{x},{q}:{y}'.format(x=a,y=b,p=c,q=d))
33 1122 p:11,q:22 p:11,q:22 p:11,q:22 p:11,q:22
- 1つ目
- 先に()内を計算してから表示
- 11+22=33が出力される
- 2つ目
- 文字列に変換して連結
- ’11’+’22’=’1122’が出力される
- 3つ目
- 数値を文字列に変換して出力
- 4~6つ目
- 3つ目と結果は同じ
- 文字列フォーマットやり方色々
数値フォーマット、タブ
a=1;b=2
print('a:%d\tb:%.2f\t' % (a,b))
a:1 b:2.00
- %d
- 数値
- \t
- タブ
- %.2f
- 小数(2fだと小数点以下2桁)
- % (…)
- 前にある%の箇所に入る数値
整形、きれいに見せる
0埋め、文字寄せ
a =1234
print(f'a:{a:06}')
a:001234
- a:06
- 前に0埋めされて6桁になる
文字寄せ
s = 'abc'
print(f'{s:_>8},{s: >8},')
print(f'{s:_^8},{s: ^8},')
print(f'{s:_<8},{s: <8},')
_____abc, abc, __abc___, abc , abc_____,abc ,
- s:…>8
- :に続く文字列で右寄せ
- s:…^8
- :に続く文字列で中央寄せ
- s:…<8
- :に続く文字列で左寄せ
環境、OSコマンド関連
path(Python内部環境変数)に追加
説明
- pathにディレクトリを追加する
- そうするとファイル名だけで呼び出しできる
- importするファイル
- 実行するプログラム
例
import sys, os
sys.path.append(os.pardir)
- 親ディレクトリをpathに追加
import sys
sys.path.append('..')
- 任意のディレクトリをpathに追加
OSコマンドを実行する
直接OSコマンドを実行する
!echo "aa" > test
!ls -l test*
-rw-rw-r-- 1 futa futa 3 Apr 3 22:38 test
- OSコマンドは「!」を先頭に付けて実行する
- ファイルtestが作成された
ファイル操作
import shutil
shutil.copy('./test','./test2')
!ls -l test*
-rw-rw-r-- 1 futa futa 3 Apr 3 22:38 test -rw-rw-r-- 1 futa futa 3 Apr 3 22:41 test2
- testファイルがコピーされ、test2が作成された
情報取得
ディレクトリ情報
from pathlib import Path
p = Path('.')
a = p.resolve()
print(a)
/home/futa
- from pathlib import Path
- pathlib.pyにあるdefのPathをインポート
- p.resolve()
- カレントディレクトリをフルパスで表示する
- Windows環境でも使える「c:\program\futa\」
- 他にも|.hom()|.cwd()|などもある
- 参考にしたページ
ディレクトリのファイル一覧取得
from glob import glob
glob('*')
['msg.sh', 'test', 'testfile',]
- from glob import glob
- glob.pyにあるdefのglobをインポート
- glob('*’)
- 「*」で全部と言う意味
- カレントディレクトリのファイル
- glob('/home/futa/*.csv’)のようにディレクトリも指定できる
- for文にするとファイルを順に取得できる
- for file in glob('*’):
- ループは次項で説明
ループ、要素集合
ループ
指定回数ループ
for i in range(3):
print(i)
0 1 2
- 0から始まる
- 3回ループする
途中でやめる(break)
for i in range(3):
print(i)
if i == 1:
break
0 1
- 2回ループする
- iが1の時に処理を抜けるので2は出力されない
飛ばす(continue)
for i in range(3):
if i == 1:
continue
else:
print(i)
0 2
- continue
- 次のループに進む
- iが1の時にcontinueされているので1は出力されない
ループのちょっとした使い方
タプルやリストを使う
for x in ('a','b'):
print(x)
for y in ['c','d']:
print(y)
a b c d
- タプル、リストについては後述
- ('a’,’b’):
- 2回ループ
- a,b順に取り出される
- ['c’,’d’]:
- 2回ループ
- c,d順に取り出される
ループに番号を付ける
for i,x in enumerate(('a','b','c')):
print(f'{i}:{x}')
0:a 1:b 2:c
- ('a’,’b’,’c’)
- タプル(後述)要素3個
- 3回ループする
- a,b,cの順に取り出される
- enumerate(…)
- 値と同時にループ番号も返す
- 設定する変数は2つ用意する(この例ではiとx)
- i,x
- iにループ番号
- xに値が入る
タプル
説明
- 読み取り専用のリスト
- ()で囲まれる
例
a = (1,2,3)
print(a)
print(type(a))
print(a[0])
a[0] = 4
(1, 2, 3)
<class 'tuple'>
1
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-953-7dcad31dc957> in <module>
3 print(type(a))
4 print(a[0])
----> 5 a[0] = 4
TypeError: 'tuple' object does not support item assignment
- 表記は(1,2,3)のようになる
- タイプは「tuple(タプル)」
- a[0]
- 0番目の要素1が取り出される
- a[0] = 4
- 値の代入はできない
リスト基本
説明
- 更新可能なリスト
- []で囲まれる
作成
a = [10,20,30]
print(a)
print(type(a))
print(f'{a[0]},{a[1]},{a[2]}')
[10, 20, 30] <class 'list'> 10,20,30
- [10,20,30]
- 中身は10,20,30の3つ
- タイプはlistになっている
- a[0],a[1],a[2]
- 順に10,20,30が取り出せる
- 0から始まることに注意
参照
b = a[0]
c = a[-1]
d = a[1:]
e = a[:2]
f = a[-2:]
print(b)
print(c)
print(d)
print(e)
print(f)
10 30 [20, 30] [10, 20] [20, 30]
- a[0]
- 番号指定(0から始まる)
- 0番目は10
- a[-1]
- 末尾から何番目
- 「-1」は末尾から1番目なので30
- a[1:]
- その番号から末尾まで
- 1番目の20、2番目の30なので[20,30]
- a[:2]
- 0番目からその番号まで(その番号は含まない)
- 0番目の10、1番目の20なので[10,20]
- a[-2:]
- 後ろから2番目から末尾まで
- 後ろから2番目の20、3番目の30なので[20,30]
要素追加・削除
a.insert(2,40)
print(a)
a.append(50)
print(a)
a.pop(2)
print(a)
[10, 20, 40, 30] [10, 20, 40, 30, 50] [10, 20, 30, 50]
- a.insert(2,40)
- 2番目(0から始まる)に40を追加
- a.append(50)
- 末尾に50を追加
- a.pop(2)
- 2番目(0から始まる)を削除
リストのちょっとした使い方
インデックス付きリスト
l = ['x','y','z']
a = list(enumerate(l))
b = list(enumerate(l, start=2))
print(a)
print(type(a[0]))
print(b)
[(0, 'x'), (1, 'y'), (2, 'z')] <class 'tuple'> [(2, 'x'), (3, 'y'), (4, 'z')]
- a
- インデックス付きのリストが作成できる
- a[0]
- 1つずつの要素がタプルになっている
- (0, 'x’)…’x’の前にインデックス番号が付く
- 0はa[0][0]、’x’はa[0][1]で取り出せる
- b
- インデックスが2から始まっている
リスト内のソート、並び替え
x = [5, 8, 4, 1, 3, 2, 7, 6]
a = sorted(x)
b = sorted(x, reverse=True)
c = x[::-1]
print(a)
print(b)
print(c)
[1, 2, 3, 4, 5, 6, 7, 8] [8, 7, 6, 5, 4, 3, 2, 1] [6, 7, 2, 3, 1, 4, 8, 5]
- sorted(…)
- リスト内がソートされた
- sorted(…, reverse=True)
- 逆順ソートされた
- x[::-1]
- 順序が逆になった
リストのループ(複数のリストをzipでまとめる)
id = [0,1,2]
name = ['x','y','z']
value = [10,20,30]
for a,b,c in zip(id,name,value):
print(f'{a},{b},{c}')
0,x,10 1,y,20 2,z,30
- zipで3つのリストが1つにまとめられる
- 3回ループ
- リストの1つ目から順に取り出される
ディクショナリ基本
作成
d1 = {1:'aa',2:'bb'}
d2 = {'01':[0,1,2],'02':[3,4,5]}
print(d1)
print(d2)
{1: 'aa', 2: 'bb'}
{'01': [0, 1, 2], '02': [3, 4, 5]}
- d1
- キー(key)は1,2
- 値(value)は’aa’,’bb’
- d2
- キー(key)は’01’,’02’
- 値(value)は[0,1,2],[3,4,5]
参照
a = d1[1]
b = d2['01']
print(a)
print(type(a))
print(b)
print(type(b))
aa <class 'str'> [0, 1, 2] <class 'list'>
- d1[1]
- キー(key)の1を指定して値(value)を取り出し
- 取り出したデータはstr型
- d2[’01’]
- キー(key)の’01’を指定して値(value)を取り出し
- 取り出したデータはlist型
キー(key)と値(value)の参照
c = d1.keys()
d = d1.values()
print(c)
print(d)
dict_keys([1, 2]) dict_values(['aa', 'bb'])
- d1.keys()
- キーのリストを取得
- d1.values()
- 値のリストを取得
ディクショナリのちょっとした使い方
キー(key)と値(value)の入れ替え
d3 = {v:k for k,v in d1.items()}
print(d1)
print(d3)
{1: 'aa', 2: 'bb'}
{'aa': 1, 'bb': 2}
- d1
- 元のディクショナリ
- d3
- 反転したディクショナリ
ディクショナリのループ
#キーごと
for k in d2.keys():
print(f'key:{k}')
#値ごと
for v in d2.values():
print(f'value:{v}')
#1セットごと
for k, v in d2.items():
print(f'{k}:{v}')
key:01 key:02 value:[0, 1, 2] value:[3, 4, 5] 01:[0, 1, 2] 02:[3, 4, 5]
- 最初の2つ
- キーを取り出す
- 2回ループ
- 真ん中の2つ
- 値を取り出す
- 2回ループ
- 後ろの2つ
- キーと値を取り出す
- 2回ループ
ディクショナリの結合(マージ)
d4 = {0:'東京',1:'神奈川',2:'埼玉'}
d5 = {0:'東京',3:'群馬',4:'栃木'}
d6 = {**d4, **d5}
print(d6)
{0: '東京', 1: '神奈川', 2: '埼玉', 3: '群馬', 4: '栃木'}
- d4とd5
- 「0:’東京’」が重複している
- {**d4,**d5}
- 重複を排除して結合(マージ)する
内包表記
if文の内包表記
説明
- 1行で書けるのでコードステップ数を減らせる
例1
for i in range(6):
a = 'odd' if i%2 == 1 else 'even'
print(a)
even odd even odd even odd
- for i in range(6):
- 0~6まで6回繰り返し
- iに順に代入される
- 'odd’ if i%2 == 1
- iが奇数の場合aに’odd’(奇数)を代入
- else 'even’
- 上記に一致しない場合に’even’(偶数)を代入
例2:サンプルコード拾い集め
for i in range(4):
offno = 8 if i%2 else 16 #偶数は16、奇数は8
im_resize = 255-im_resize if (im_resize==0).sum() > 224*112 else im_resize
リスト内包表記
説明
- ループしながらリストデータを作成できる
例1
a = [x for x in range(10)]
b = [x for x in range(10) if x % 2 == 1]
print(a)
print(b)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [1, 3, 5, 7, 9]
- a:for文
- for x in range(10)
- 0~9までxに入る
- [x …]
- xを実際の値に展開する
- for x in range(10)
- b:for文+if文
- aの例にif文(条件)が追加
- if x % 2 == 1
- 条件に合致する場合のみxが作られる
- 2で割った余りが1=奇数
例2:サンプルコード拾い集め
#i[0]はimg_list[0]のshapeが(28,28,5)だったのでそのための調整
ims = [plt.imshow(i[0], animated=True) for i in img_list]
#type(dataset_dir)→「pathlib.WindowsPath」なので「/」でxとつなげられる
img_datasets = {
x: datasets.ImageFolder(dataset_dir / x, data_transforms[x])
for x in ["train", "val"]
}
dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}
ims = [plt.plot(Y[i], animated=True) for i in range(len(Y))]
関数
基本形の確認
定義
def a(x,y):
print(f"{x},{y}")
a?
Signature: a(x, y) Docstring: <no docstring=""> File: ~/<ipython-input-934-e6ce9aac0df0> Type: function
- Signature
- 関数の呼び出し方法
- Type
- functionになっている
実行
a(1,2)
1,2
- a(1,2)
- 引数x=1,y=2が代入された
- 引数の値1,2が出力された
引数(*、**の使い方)
定義
def f(*args, **kwargs):
print(args)
print(kwargs)
f?
Signature: f(*args, **kwargs) Docstring: <no docstring> File: ~/<ipython-input-977-5a77e4d4f5a8> Type: function
- args,kwargsこの文字列はなんでもよい
- Signature
- 関数の使い方
- f(*args, **kwargs)
- Type
- functionになっている
実行
f(1, 2, a=3, b=4, c=5)
(1, 2)
{'a': 3, 'b': 4, 'c': 5}
- *argsに該当する箇所
- (1, 2)
- 関数内ではタプルとして利用できる
- **kwargsに該当する箇所
- {'a’: 3, 'b’: 4, 'c’: 5}
- 関数内ではディクショナリとして利用できる
関数省略形(lambda)
説明
- 関数が簡単な処理を行うだけの場合を想定
- 1行で関数が書けるので、コードステップ数を減らせる
宣言
sq= lambda n : n**2
print('4を二乗すると'+str(sq(4)))
print('5を二乗すると'+str(sq(5)))
4を二乗すると16 5を二乗すると25
- sq
- 今回定義する関数名
- 二乗する機能を持った関数
- lambda n :
- lambdaで関数を宣言
- nが引数の変数名
- この例では引数は1つ
- n**2
- 関数の処理(簡単な処理)
- ここでは引数nを二乗(べき乗)する
呼び出し
a = sq(3)
print(a)
9
- sq(3)
- 関数を引数3で実行した
- 引数n=3が二乗されて9を返す
関数その他
覚書
#アノテーション
def __init__() -> None:
#プログラム実行に必要な記述
if __name__ == '__main__':
クラス
基本形の確認
定義
class a:
def __init__(self):
self.x=1
def __call__(self, p, q):
print(self.x)
print(f"{p},{q}")
インスタンス作成
ca = a()
ca?
Signature: ca(p, q) Type: a String form: <__main__.a object at 0x7ffa70d7f340> Docstring: <no docstring>
- ca = a()
- caの名前でクラスが利用できるようになった
- コンストラクタ(def __init__)が実行された
- 内部変数(self)のxに1を代入
- Signature
- クラス呼び出し方法
- Type
- クラス名
クラス実行
ca(2,3)
1 2,3
- Signatureに書いてある通りに呼び出す
- ca(2,3)
- 実行部(__call__)が実行された
- 引数はp=2、q=3
- 内部変数1と引数p,qが出力された
便利なロジック集
文字列操作
「/」で区切る
from pathlib import Path
a = Path('.').resolve()
b = str(a).split('/')
print(a)
print(b)
print(type(b))
/home/futa ['', 'home', 'futa'] <class 'list'>
- pathlib.Path
- .resolveを使ってカレントディレクトリパス取得
- このページの前半でも説明
- str(a).split('/’)
- .splitを使うために文字列に変換
- 区切り文字は「/」
- 配列に格納された
- 例えば、現在のディレクトリ名を取得したい場合
- str(a).split('/’)[-1]→「futa」が取れる
.splitの利用例
label = p.split("/")[2] #"/"で区切って3番目 #pにはディレクトリのパス
label = 1 if label == "bees" else 0 #ハチ(bees)だったら1それ以外は0
- 画像認識AIの学習データ
- 昆虫の画像が集められていてディレクトリ名がアノテーションされている
- ハチ(bees)を認識するAIの学習データとしてハチを1それ以外を0とするラベルを作る
文章(改行含む)から文字列を検索する
文書作成
!echo -e "aa\nbb" > test
!cat test
aa bb
- 改行を含む文書
ファイル読み込み
a = !cat test
print(a)
print(type(a))
['aa', 'bb']
- 1行ごとにリスト形式で読み込まれる
配列データを連結
b = '\n'.join(a)
print(b)
print(type(b))
<class 'IPython.utils.text.SList'> aa bb <class 'str'>
- '\n’.join(…)
- 引数に配列を指定する
- つなぐ文字は「\n」改行コード
- 変数に文章を読み込む流れ
1)前項のaに文章を配列として格納
2)配列の連結joinを使ってつなぐ(改行コードを挟む)
3)変数に文章が読み込まれた
文字列検索
c = b.find('aa')
d = b.find('bb')
e = b.find('cc')
print(c)
print(d)
print(e)
0 3 -1
- c
- aaが見つかった位置は0
- d
- bbが見つかった位置は3
- 改行コードも1文字として数える
- e
- 見つからない場合は-1
- つまり、見つかった場合は0以上になる
役に立つかもしれないもの覚書
情報
#関数の機能を参照する
dir(tuple)
#オブジェクトIDを参照する
id(soeji)
文字列操作
a.replace('\n', ' ') #改行をスペースに置き換え
a.strip() #両端の空白文字を削除
a.strip("a b c") #両端の指定の文字を削除(間は削除されない)
'\n'.join(b.split(' ')) #スペースを改行に変更
timeオブジェクト(経過時間取得)
import time
since = time.time()
#(処理)
time_elapsed = time.time() - since
generator作成
- returnの代わりにyieldを使うdef(関数)
- for文やnext(…)が使えるようになる
静的関数
class xx:
@staticmethod
def xxx
- クラスインスタンスを作成しなくても利用できる
- self.xxxのようにクラス内で関数を呼び出せる(多分こっちの方が利用用途が多い)
- 参考にしたページ
zipファイル解凍読み込み
import gzip
with gzip.open(filename, 'rb') as f:
labels = np.frombuffer(f.read(), np.uint8, offset=8)
- numpy.frombuffer(buffer, dtype=float, count=-1, offset=0)
- np.frombufferの説明記事
- NumPy:【組み込み関数】便利そうなもの
