読者です 読者をやめる 読者になる 読者になる

kentsu.log

何かその時の興味でいろいろする人。最近はScala使ってる。アルゴリズムと自然言語処理、深層学習が大好き。

python入門

はじめに

最近OpenCVpythonで扱うことが多くなったので一度しっかりと勉強してみる
今回は自分の備忘録として書くようなスタイルなので、ある程度プログラミング言語を他に扱えることを想定している
なので、ところどころ説明を省くので全くの初心者が見るべきではない
それと多々、javaと比較することがある(自分が一番得意としているから)

今回はpython2.7.6を使用していく

文法以前の基本的な事項

ここではまず基本的な事項、コメントやソースエンコードなどそういったことをまとめていく

ソースコードエンコーディング

これからpythonでコードを書いていく上で、対話型は使わずにソースファイルを作成しそれにソースコードを書いてくスタイルでやるので
ソースコードエンコーディングというものが必要になる

#coding:utf-8

をソースファイルの先頭に記述するだけでいい
これでコメントや文字列リテラルに日本語を使用できたりする
emacsでは-*-とやるみたいだが普段からvエディタはvimしか使わないのでそこは割愛する

コメント

ソースコードエンコーディングでも登場した「#」がコメントを表す
なのでpythonでコメントを各場合はこうなる

#これがコメント(coding:utf-8前提)

変数

まずは数値や文字列などをやる前に変数について
pythonで変数は

hello = "hello,world"
print hello  #print->hello,world

のように

変数名 = オブジェクト

という形をとり、作成とオブジェクトの代入がまとめて行われる
つまりこれまでのjavaやCといった言語のように宣言だけ先にしておくことはできない
それと関係して一度もオブジェクトが代入されていない変数を使用しようとすると「NameError」が発生する

また型推論なので変数にデータ型を指定することは必要ない

変数名の付け方はいつもどおり

オブジェクトの再代入はデータ型の制約がないため、全く別のオブジェクトでも代入可能つまり

number = 123
number = 3.14 #浮動小数点もok
number = "math"#極論これもok

更に変数を変数に代入することもいつもどおり可能
その他のプログラミング言語で採用してるもろもろのこともできる

ただし数値と文字列は演算することはできなく

num = 1
str = "hello"

print str+num

ということもできない

あと二項演算子も使用できる

数値

数値リテラルはいつもどおりなところが多いけど型推論な分多少注意が必要なのが
長整数と複素数

12000000000000000000000000000L#長整数
0+2j#複素数

長整数はざっくり言えばlongのことだから末尾にL,lが必要
だけど実際はこれすら推論されるから変数に代入するときは大して気にする必要がない

問題は複素数
実部虚部ともに宣言可能で虚部にはjをつける
また以下のように、実部虚部それぞれ取り出すことができる

c = 1 + 2j
print c.real
print c.imag


四則演算は少し今までの言語と違う部分がある
基本的に+,-,*,%,/が使えることに変わりはないが、**という累乗を表す演算子と//という小数点以下切り捨ての演算子があり
以下のように使用する

print 17.0//5 #print->3.0
print 5 ** 2 #print->25

累乗は

基数 ** 指数

という形になる

さっきの演算のところでもいったが文字列と数値は演算できない
そのため文字列を整数に変換することを考える
更には小数も整数に変換することを考える

まず前提として以下のようなことをすると

1 + "2"

「TypeError」が発生する
そこでint関数というものを使用しこうする

print 1 + int("2") #print -> 3

int関数は結構便利で基数を設定することもできる

print int("10",10) #基数10 print -> 10
print int("10",8) #基数8 print -> 8
print int("10",16) #基数16 print -> 16 

なので基数を16にした場合はA~Fまでのアルファベットも使えるが
10の時にそれらが含まれていると「ValueError」がでる

小数に対して使用された場合は0の方向に小数部が丸められる

文字列

リテラルはいつもどおりのダブルクォーテーション
ただしpythonはトリプルクォーテーションなるものがある

"""hello,world"""

これは複数行にわたって文字列が宣言でき、"""内の改行は\nに置き換えられる
更に便利なのはraw文字列というものがあって先頭にr,Rをつけると文字列内の\はそのまま扱われる

数値と文字では演算ができなかったが文字列同士では+で連結することができる

print "hello"+"world" #print -> helloworld

pythonには更に謎な機能があって
文字列を繰り返すことができる

"hello"などの文字列の後に * 回数 とすることでその文字列を繰り返すことができる

print "hello" * 3 #print -> hellohellohello

文字列の長さがlen()関数で行う

print len("hello") #print -> 5


数値と文字列は連結できないので文字列を整数にする方法を紹介した
今回はその逆で数値を文字列に変換する

それはstr関数によって行われ整数以外に小数も扱う

print 1 + str(2) #print -> 12

文字列オブジェクトはインデックスを指定することで文字を切り出すことができる

hello = "hello"
print hello[0] #print -> h

さらに文字だけでなく部分文字列も切り出すことができて
以下のようにする

hello = "hello"
print hello[1:3] #print -> el

条件分岐

いつもどおりのif文から
ただしいつもなら{}を使うがpythonはブロックがインデントで分けられるので
ちょっと勝手が違う
更にいうとelseifはelifでelseはいつもどおりelse

age = 18

if age < 20:
    print "未成年"
elif 20 <= age:
    print "成人"
else:
    print "エラー"

ここで注意したいのがtrue or false
pythonではTrue or Falseで先頭が大文字になる
また0は偽として扱われ、それ以外は真になる
空文字列も同様に偽となり空出ないなら真である
空のタプル、リスト、ディレクトリは偽であり真はない
Noneも同様

比較演算子はいつもどおりのものが揃っていてそれ以外はない
ちなみに==で文字列も評価できるがそれは値を比較しているだけであってオブジェクトを比較しているわけではない

なのでオブジェクトを比較するときはis,is notを使用する

また論理演算子は少し違って
&& -> and

-> or

! -> not
となる

リスト

pythonでは配列とjavaのCollectionのlistを足して2で割ったようなリストというものがある
宣言では{}ではなく[]を使用して以下のようにする

list = [1,2,3,4,5,6]

また含まれるオブジェクトは1種類に統一する必要はなく、数値と文字列のように混ざっててもいい
また更にいうとリストオブジェクトは別のリストオブジェクトを要素にできるから局所的に多次元配列のようにもできる

要素をインデックスで参照するときは

#list = [1,2,3,4,5,6]を仮定
print list[0] #print -> 1

となる、つまりいつもどおり

文字列でスライスを使って部分文字列を取得した時のように
リストに対してもそれは同様におこなえる
ただ説明してなかったのは、スライスで片方を省略したり、負の数が使えることである

#上記のlistを仮定
print list[3:] #print -> 4,5,6
print list[:3] #print -> 1,2,3
print list[1:-1] #print -> 2,3,4,5

要素の変更はいつもどおり行えるが
素数の違う部分配列をまとめて変更することも出来る

リストのサイズに関してはlenで取得できる

リストに要素を追加する場合はappend関数が使える
別のリストの要素を追加するときはextend関数を使う

list = [1]
list.append(2)
list.append(3)

list.extend([4,5,6])
print list #print -> 1,2,3,4,5,6

またリスト同士の連結は+で連結出来る
さらに文字列と同じようにリストを繰り返すことも出来る

listにインデックスを指定して要素を追加したい場合は
insert関数を使う

list = [1,2,3]
list.insert(1,4)#insert(インデックス,要素)
print list #print->1,4,2,3

リストの要素を削除するときはdelが使える

list = [1,2,3]
del list[0]
print list#print->2,3

指定インデックスの要素を削除するときはpop関数でインデックスを渡す
逆に指定の要素を持つ部分を削除するときはremove関数で引数に要素を渡す

スライスを使えばこれらのことが意外と簡単にできたりする

リスト[len(リスト):] = オブジェクト

で末尾に挿入ができる

また部分リストに対して[]を代入することでその要素を消すことができるが
スライスで部分リストを取得してない時には使えない


リストにある要素が存在するかどうかを確かめたいときはinを使う

list = [1,2,3,4,5]
if 2 in list:
    print "yes"

#print -> yes

逆に存在しない時はnot in

指定した要素が存在しそのインデックスを返すのはindex関数
これに引数としてインデックスを確かめたい要素を渡す
存在しないなら「ValueError」がでる

リストに含まれるある要素の個数を数えたいならcount関数に
カウントしたい要素を渡す

ソートはsortとreverseでjavaのCollectionsと同じ


連続した数値のリストを作成したいときはrange関数を使う

list = range(5)
print list #print -> 0,1,2,3,4

list2 = range(2,5)
print list2 #print -> 2,3,4 開始位置を宣言することができる

list3 = range(1,6,2)
print list3 #print 1 -> 1,3,5 stepを宣言できる

タプル

リストとほぼ同じことができるが宣言がすこし違う

tuple = (1,2,3,4,5)

と()でくくる
ただし要素がひとつだけの時は

tuple = (1,)

と最後に,をつける必要がある

要素の取得はリスト同様[]でインデックスを指定する
スライスとサイズの取得も同様、連結と繰り返しに関しても同じことが言える
tuple関数というものを使えばリストからタプルを生成できたりもする

辞書オブジェクト

これはjavaでいうMapとほぼおなじ

dict = {"java":1,"python",2}

のように{}で宣言する

キーに対応する値を取得したいなら[]でインデックスのようにキーを渡す
値の変更とサイズの取得もリストやタプルに同様

連結は

辞書オブジェクト.update(辞書オブジェクト)

キーの削除はdelが同じように使える
辞書オブジェクトに対してはpop関数は削除したキーに対応する値を返す

任意のキーを削除するならpopitem関数を使用
このとき選ばられるセットはランダムである

clearですべて削除できる


キーが含まれているかを確かめるのはin
キー in 辞書オブジェクト
not inも使える

inと同じ動作をするものでhas_key()もある

またkeys関数を実行することでキーをすべてリストとして取得できる
それは値にも使えて値をリストで取得したいときはvalues関数
(キー、値)のタプル形式ですべて取得するときはitems関数

ループ

まずはwhile文

while True:
     print "always true"

となる、つまりいつもどおり
ただしループを抜けた時の処理をelseで書ける

while True:
    print "always true"
else:
    print "error"

次にfor文

for i in [1,2,3,4,5,6]:
    print i

#print i -> 1,2,3,4,5,6

for文に対してもelseは適応できる
更に今はリストを渡していたがrange関数でわたすこともできる