#はじめに
意外なことに、B4になってプログラミング言語がC言語しか使えない人がいるらしい。
まぁ確かに公に授業ではC言語しか扱ってないし、当然と言えば当然ですな。
しかしながら、ちょっとした計算やアルゴリズムを実装するのに毎回C言語を使うのは非常に非効率なのではないかと。
変数宣言して~、メモリ確保して~、あ、セミコロン忘れた。
まー面倒くさい。
適当にちゃっちゃと試作的なプログラムを組むのにはPythonは良いと思う。
正直他をほとんど知らないんだけども、まぁとりあえずPythonで良いと思う。
僕自身は全然Pythonを使いこなしてるわけではないんですけども、とりあえずC言語やった知識で適当にプログラム書く分には必要十分です。
そこで、Advent Calendarに書くものも特に思いつかないので、C言語を一通りやった人向けにPython入門的な記事でも書こうかなってなりました。主にB3以下がというかもろにB3以下がターゲットです。
ついでにということで筆者はこれまでPython2系だけでやってきたんだけど、Python3系をここで扱えば自分の勉強にもなるかなと思ってPython3系ということで。
#環境構築
あー環境構築かめんどくさいなーって言いながら、ubuntu 16.04 LTSでターミナルを開いて、
ってやると、
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
ってなります。
なんか入力受付状態になるのでとりあえずCtrl-Dで止めましょう。
(これは対話型シェルとか呼ばれているものでこの記事では触れません。)
実はPython3はubuntuに既に入ってます。やったね。
(ちなみにpython3
じゃなくてpython
ってやるとPython2が動きます。)
ubuntu以外の人ですが、普段から他のLinux使ってる人は強い人なので心配ないと思います。というかこの記事読まないでください恥ずかしい。
Windowsの人は、Python公式からソフトウェアをダウンロード出来たりもするし、Bash on Ubuntu on Windowsとか、VMware使って仮想でubuntuいれると良いんじゃないでしょうか。他にも使えるだろうし。
Macの人?Mac持ってるんだしその目の前のMacで自分で調べてください。(もしかしたらubuntuと一緒で最初から入ってたりするのかな、知らんけど。)
#ハロワ
さっそくかの有名な最初のプログラムを動かしましょう。
vimなりemacsなりでprint.pyとか適当に名前付けて次のファイルを作って下さい。
print("Fuck eeic")
でコマンドラインで
ってやると
ってなります。むっちゃ簡単です。コンパイルとかいうの無いです。セミコロン?改行で察しろよってことですね。
ファイルの保存とか実行とかもう挙げないんで、同様にしてどんどん行きましょう。
#変数
Pythonでは変数の宣言とか要りません。代入するものをそのままぶっこんで下さい。
文字列から整数へのキャストとかもできます。
間違ってたらプログラミング実行のときにエラーが出るのでとりあえずやってしまえ精神が育まれます。
a = "3"
b = 2
c = int(a) / b
print(a, b, c)
3 2 1.5
C言語と違って、またPython2と違って、Python3では整数/整数が小数で出るようになったみたいです。よく間違えてる所なのでちょっとだけ有難い。
演算子を少し変えて、c = int(a) // b
とすればいつも通り整数値になります。
#制御文
if
とfor
とwhile
です。
while
は割とそのままだけど、if
はちょっと、for
は大分C言語とは違うと思います。
なにはともあれ、「インデント」が一番独特です。
C言語では括弧で括って範囲を表していたのが、Pythonでは:
とインデントで制御の範囲を表します。
a = True
if a != True and a == False:
print(1)
elif a == None:
print(2)
else:
print(3)
print(range(10))
sum = 0
for i in range(10):
sum += i
print(sum)
sum = 0
i = 0
while True:
sum += i
i += 1
if i >= 10:
break
print(sum)
3
range(0, 10)
45
45
if
、else
ともう一つelif
なるものがあります。else ifの略なんだろうけどちょっと変なの。
条件にand
があって、そしたらもちろんor
もあって、Cの&&
と||
の代わりになってます。
筆者はコメント頂くまで気づいていなかったのですが、Pythonに&&
と||
は存在しません。注意。
for
はfor i in range(10):
とかいう良く分からないので動きます。
range(10)
をprintしてみるとrange(0, 10)
とかいう更に良く分からないのが出てくるんですけど、とりあえずこれでi
には0から9(10-1)までの整数が入ってループするようになってます。
うん良く分かんない。
補足。
コメントに頂いたようにprint(list(range(10)))
とすれば[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
となって、次に扱う「リスト」というものになっていることがわかります。
Python2ではリストへのキャストなどせずにprint(range(10))
でこのリストが得られ、ここで紹介するforが、(これまた次で扱う)リストを使ったfor
と同じ操作であることが非常に分かりやすいのですが、残念ながらPython3では仕様変更となりました。
これは悪いことではなくて、メモリ管理的にはグレードアップです。
この記事では動けばいいくらいの心持ちを前提に話を進めているので、上記のような適当な説明というか誤魔化しに留めています。
詳しく知りたい人は「range xrange」や「Python 2 3 違い」とかでググってください。
インクリメントのsum += 1
ですが、sum++
とは出来ないので注意。
while
はそのままだと思います。break
もC言語と一緒。コードには書いてないけどcontinue
もC言語と同様にあります。
#リストと辞書
C言語でいう配列の代わりにPythonにはリストというものが、構造体の代わりには辞書というものがあります。
いや構造体の代わりはクラスです。でもとりあえず適当にプログラム書く分には辞書で間に合いますので辞書を紹介します。
lst = [1, 2, 3]
print(lst[1])
lst.append(4)
print(lst)
lst.remove(2)
print(lst)
for neko in lst:
print(neko)
dct = {'year':2016, 'month':12, 'day':6}
print(dct['year'])
dct['hour'] = 0
print(dct)
del dct['month']
print(dct)
2
[1, 2, 3, 4]
[1, 3, 4]
1
3
4
2016
{'year': 2016, 'day': 6, 'hour': 0, 'month': 12}
{'year': 2016, 'day': 6, 'hour': 0}
Pythonではリスト(配列)を扱う際にmalloc
は必要ありません。
Pythonが勝手に管理してくれます。頭いい。
リスト変数に対して.append()
や.remove()
といった初めて見る表記の関数的なものがありますが、これは所謂オブジェクト指向というやつで、リストというオブジェクトに対してのみ使えるものです。
append(lst, 2)
みたいなものです。まぁ気にしないで飲み込んでください、順番変わってるだけだし。
リストの中身を要素と呼ぶんですけど、appendは要素をリストの末尾に追加、removeは指定した要素を削除(厳密にはリスト内の先頭に一番近い、指定した値と同じ要素を削除)という操作です。
リストを使ってfor neko in lst:
という操作をしているんですが、これはちょっと見慣れないかもしれません。
これはlst
という名前のリストから要素を一つずつneko
に代入してループを回すという操作をしています。
lst = [1, 3, 4]
であれば一週目はneko
には1
が、二週目にはneko
には3
が、三週目にはneko
には4
が代入されてループを回ります。
辞書も初期値入力や要素の追加削除は分かりやすいと思います。
リストの.remove()
を見た後だとdel
ってなんだよって感じですが、うーん、なんでしょうねこれ。
まぁ消したいものが消えればいいじゃないですか。
del
は他の変数を消したい時にも使う結構汎用なやつです。
リストと辞書は要素としてなんでも、つまり数値や文字列だけでなく、リストの中にリストや、辞書の中に辞書、リストの中に辞書などなど色々突っ込むことができます。
うまく使えれば大体のデータはこれで操作しきることが出来たりします。
#関数
自分で好きな関数を作りましょう。
関数の代表作といえばswapですね。
def swap(a, b):
tmp = a
a = b
b = tmp
return a, b
a = "neko"
b = "inu"
print(a, b)
a, b = swap(a, b)
print(a, b)
neko inu
inu neko
ここでも:
とインデントで範囲を指定していますね。
C言語ではポインタを渡して、ポインタの参照先に対して操作することでswapを実現しますが、色々ゆるゆるなPythonでは関数の返り値も柔軟にいじれるのでこのような適当なコードでもちゃんと動いちゃいます。
というかswapは特に関数例が思いつかなかっただけで御座いまして、関数をわざわざ作る必要はありません。
a, b = b, a
で出来ちゃいます。
しかしながら、とはいえ適当に書きすぎると痛い目を見ることがあります。
def list_reverse(lst):
lst.reverse()
return 0
def add(a):
a += 1
return 0
lst = [1, 2, 3, 4, 5]
lst2 = lst
print(lst)
list_reverse(lst)
print("lst :", lst)
print("lst2:", lst2)
a=1
add(a)
print(a)
[1, 2, 3, 4, 5]
lst : [5, 4, 3, 2, 1]
lst2: [5, 4, 3, 2, 1]
1
リストの並び順を入れ替えるという操作.reverse()
を、わざわざ関数内で行うという無駄な関数list_reverse()
を作りました。
値を渡しているだけなら本当に無駄ですね。
しかし、関数にリストを渡して関数の中で逆順にしているだけで元のリストには影響がないと思いきや、元のリストにもろに影響が出て逆順になっています。
これはリストは基本的にポインタ的な扱いをされているのが原因です。関数に参照渡しをするので関数の操作が元のリストに影響します。
lst2 = lst
と代入がありますが、これも値のコピーではありません。リストは基本的に参照渡しなので、なんとこの二つのリストは同期してしまっていて同じものとなっています。
その証拠に関係ないはずのlst2
も逆順になっていますね。
一方変数a
は関数add()
でインクリメントされてても全く影響がありません。これは値渡し(みたいなもの)だからですね。
調べて見たら全部参照渡しみたいです。値を変更すると、①[参照先も変える型]と、②[急に別領域を確保して参照先を変える型]に分かれているみたい。めんどって思ったけど確かにメモリ管理的には正しいなぁ。
参考:Pythonの値渡しと参照渡し
#import
Pythonはライブラリが豊富らしいです。よく知らないんですけど、確かにこんな関数ないかなって調べると大体ライブラリがあってよくお世話になっている気がします。
C言語では#include<>
でしたがPythonではimport
なんです。
import copy
def list_reverse(lst):
lst.reverse()
return 0
lst = [1, 2, 3, 4, 5]
lst2 = copy.deepcopy(lst)
print(lst)
list_reverse(lst)
print("lst :", lst)
print("lst2:", lst2)
[1, 2, 3, 4, 5]
lst : [5, 4, 3, 2, 1]
lst2: [1, 2, 3, 4, 5]
import copy
とlst2 = copy.deepcopy(lst)
ですね。copy
さん家の.deepcopy()
ちゃんを使わせてもらいました。
出力を見てお判りでしょうが、今回のlst2
は.deepcopy()
ちゃんを使ってlst
の値をコピーしただけなのでlst
とは同期していません。やったね。
#おわりに
ハロワ、変数、制御文、リストと辞書、関数、importと基本的なところは一通り触れられたかなと思います。
変数でいえば複素数とか、制御文でいえばswitchとか(Pythonにswitchは無かった!!)、色々と触れていない部分も多々あります。
それでも一通りC言語をやった人であれば、「この機能ないの?」とか思ったらググればいいんです。どうせあります。
冒頭にも述べましたが、とりあえずC言語しか触ったことがない人、特にB3以下の人がPythonを触るきっかけになればいいなと思って書きました。授業の課題をいちいちC言語でやってたら体が持ちませんよ?Pythonでなくても良いので他のさっと書ける言語を触るべきです。
Python3の勉強になればいいなとも思ってたんですが基本的な部分ではprintぐらいしか違いがなかったので結局あんま意味なかったです。
今更ですが私は未だにオブジェクト指向のプログラミングが書けません。のたのたと手続き型を書いてその場を凌いでします。
それでも一応研究らしいことは(多分)出来ているので、今回書いたものは研究らしいことをやるのに多少は役に立つんじゃないでしょうか。
それにしても我ながら面白くない記事書いてしまったなぁ
あ、そしたらついでにAdvent Calendarのハードル下げになれば幸いです。
(訂正コメントありがたいです)