Python
python3

Python初心者が感じたこと(変数とファイルの読み書き)

はじめに

Matlabで今までやってきましたが,機械学習を行う上で,プログラミングを本格的にやってみようと決意して,はや2か月がたちました
遊びで機械学習をやってみたくて,0からはじめるDLなどを読破して,アルゴリズムの面白さに気づき,AtcoderでC問題とD問題に苦戦している現在です.蟻本も読み進めている最中,Tensorflow系の本も読んでみてます
そこで,今までPythonで苦戦したことをまとめます

目的

Pythonに必要とされる知識の共有(初心者)
特にMatlabというものから移行される方

Pythonのversion

python 3.6.4

変数宣言

copyというやつ

これは一番難しいところではないでしょうか!
immutable と mutableについては後で触れます.とりあえずは基本の考え方
Pythonは変数を

sample.py
a = 1
b = a

print('a_address = {0}'.format(id(a)))
print('b_address = {0}'.format(id(b)))

#Result
#a_address = 1620864480
#b_address = 1620864480

のように宣言すると,同じアドレスが入ります
よく言われるように名札を数に貼り付けてます.
つまりこの場合はa, bが同じ場所を指しているのは明確です.

で,immutableなら問題ありません.コピーしてみましょう

sample2.py
a = 1
b = a

print('a_address = {0}'.format(id(a)))
print('b_address = {0}'.format(id(b)))

a = a + 1

print('a_address = {0}'.format(id(a)))
print('b_address = {0}'.format(id(b)))

#Result
#a_address = 1620864480
#b_address = 1620864480
#a_address = 1620864512
#b_address = 1620864480

いわゆるMatlabっぽく動きました.変数を宣言しなくても,そのままそこに入ります.そしてそれを扱えるということです.

で,ここまでが分かるとimmutable と mutableの話につながります
mutableは配列ですが,

次のようなケースを考えてみましょう

php.sample3.py
a = [1]
b = a

print('a_address = {0}'.format(id(a)))
print('b_address = {0}'.format(id(b)))

a.append(2)

print('a_address = {0}'.format(id(a)))
print('b_address = {0}'.format(id(b)))
print('a = {0}'.format(a))
print('b = {0}'.format(b))

#Result
#a_address = 1706568184776
#b_address = 1706568184776
#a_address = 1706568184776
#b_address = 1706568184776
#a = [1, 2]
#b = [1, 2]

これが一番危険なパターンですね
よく考えると普通なのですが,初心者だとやりがちです.

こんな例もあります

php.sample4.py
a = [1]*2
b = a

print('a_address = {0}'.format(id(a)))
print('b_address = {0}'.format(id(b)))

a[0] = 2

print('a_address = {0}'.format(id(a)))
print('b_address = {0}'.format(id(b)))
print('a = {0}'.format(a))
print('b = {0}'.format(b))

#Result
#a_address = 2181161940040
#b_address = 2181161940040
#a_address = 2181161940040
#b_address = 2181161940040
#a = [2, 1]
#b = [2, 1]

で,何をどう気をつけるべきなのか?

変数同士を=でつなげた場合は,いったんはそれらが同じものを示していると考えてください!!!!

そのあとにmutableやimmutableうんぬんで話が変わってきますので

これにつきると思います

前に書いたNNのプログラムはこれで動きませんでした.
もし,コピーしたい場合は

import copy 

でcopyやdeepcopyを使ってください

関数におけるもの

さて,この問題は関数においても発生します

pythonは関数が,参照渡しです.なので変更されたら変更されます
ご指摘いただいたように,pythonは関数が,値渡しだそうです.勘違いしてました....
”値(オブジェクト)への参照値を渡します。” しっくりきました!ありがとうございます.

ただし,配列などのmutableなものですが
以下を見てみてください

sample5.py
def sample_int(a):
    a = 1

def sample_array(b):
    b[0] = 1

if __name__ == '__main__':
    a = 2
    print('a = {0}'.format(a))
    sample_int(a)
    print('a = {0}'.format(a))

    b = [0, 0]
    print('b = {0}'.format(b))
    sample_array(b)
    print('b = {0}'.format(b))

#Results
#a = 2
#a = 2
#b = [0, 0]
#b = [1, 0]

はい...
こういうことです.
まぁそもそもやっていることが不自然なので仕方がないようにも思います!

・return で別の値を返してそれを使う作戦
・タプルにしてから渡す

がメインの手法だと思います

ファイル読み込み

苦戦しました...
まず,ファイルを読み込む→処理→書き出し という作業はできないと企業のコーディングテスト含め,絶対受かりません(落ちまくりました)
単純なことですが,できるようになった方がいいと思います.
僕はmatlab出身なので,(Python育ちになりかけてますが),csvとtxtを読み込む機会が多いのでその2つをまとめておきます(長くなったのでcsvは次回にします)

txtで簡単にやる場合

ワンポイントテクニック

これよくatcoderとかでも使いますが文字列をリスト化すると分かれてくれます

sample6.py
a = input()
#aaaと入力
b = list(a)
#['a', 'a', 'a']

書き込み

txtを簡単に読み書きするにはopenを使います

sample7.py
f = open('sample.txt', 'w')
f.write('test')

当たり前ですが,writeの引数はstrです
さて,改行して書きたいときは,

sample8.py
f = open('sample.txt', 'w')
f.write('test')
f.write('test_2')
f.close()

これだと,くっついて出力されてしまいます
なので,\nで区切るか,(これだとめんどくさいので)

sample9.py
f = open('sample_2.txt', 'w')
f.write('test\n')
f.write('test_2')
f.close()

または

sample10.py
f = open('sample_3.txt', 'w')
text1 = 'I am a dog'
text2 = 'You are a cat'
text3 = [text1, text2]
text = '\n'.join(text3)
f.write(text)
f.close()

のようにしてもよいです.こっちの方がスマートですね.
これだと改行して出力されます.

ちなみにwritelinesはstrの配列を渡すとそれをそのまま書いてくれますので!(改行はされません)

上書きしたいなという人は,'w'を'a'にすれば追記モードになります!

読み込み

同じくopenでよみこみますが,readを使うとこうなります(まるごと読み込まれます)
ここで注意点はスペースと改行文字\nも読まれます

sample11.py
#sampleには aaa\nbbb となっているとします
f = open('sample.txt', 'r')
a = f.read()
a = list(a)
print(a)
f.close()
#出力は['a', 'a', 'a', '\n', 'b', 'b', 'b']

なので分けたい場合は

sample12.py
#sampleには aaa\nbbb となっているとします
f = open('sample.txt', 'r')
a = f.read()
a = list(a.split('\n'))
print(a)
f.close()
#出力は['aaa', 'bbb']

とすれば良いです.では,readlineとreadlinesをどう使えばよいでしょうか?
readlinesはまるごと読まれます(改行文字も含まれます)

readlineは1行のみです
全部読みたい場合は,while文かfor文で回してください

プログラムをみてみます

sample13.py
#sampleには a a a\nb b b となっているとします
f = open('sample.txt', 'r')
a = f.readlines()
a = list(a)
print(a)
f.close()
#出力は['a a a\n', 'b b b']
sample14.py
#sampleには a a a\nb b b となっているとします
f = open('sample.txt', 'r')
a = f.readline()
print(list(a))
f.close()
#出力は['a', ' ', 'a', ' ', 'a', '\n']

なので,これらを用いれば改行と空欄(スペース)を区切って値を取得できます
replaceを用いていますが,stripでも良いです

sample15.py
#sampleには a a a\nb b b となっているとします
f = open('sample.txt', 'r')
a = f.readlines()
print(list(a))
b = []
for i in a:
    b.append([i.replace('\n','').replace(' ','')])
print(b)
f.close()
#出力は['a a a\n', 'b b b']
#[['aaa'], ['bbb']]
sample16.py
f = open('sample_3.txt', 'r')
b = []
a = f.readline()
while a:
    a = a.strip()#間は消されませんので
    b.append([''.join(a.split())])
    a = f.readline()

print(b)
f.close()

になります

最後に

pythonはかなりわかりやすい言語ですが,慣れるまで頑張ります.
次回はcsvについて書いてみます
その次はアルゴリズムについてや,NNについてもそのうち書いていきます

Twitter:https://twitter.com/ShunichiSekigu1
github:https://github.com/Shunichi09