【全部まとめ】AI開発に必要なPython


前提

プロンプトへの出力

これだけは覚えておく

リテラル

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 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を実際の値に展開する
  • 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

zipファイル解凍読み込み

import gzip
with gzip.open(filename, 'rb') as f:
    labels = np.frombuffer(f.read(), np.uint8, offset=8)


Posted by futa