Pythonプログラミング

後期高齢者の学習内容

15年前までは,予算の少ない地方国立大学で,FORTRAN言語で書かれた分子軌道計算やX線解析プログラムを大型計算機からワークステーションやパソコンに移植して使用していた.定年後私大へ移った頃には,解析アプリを組込んだ専用サーバの使用が主流になり,GUIアプリをブラックボックス的に利用するのが当たり前になった.プログラミングの経験があるとはいえ,私大定年後かなりの時間が経ち,80歳を前にしてそれなりの不安を懐きながら Python言語に挑戦してみた.結論的には,コードがシンプルで分かり易く,ライブラリの豊富さ,汎用性が高い点では昔の言語には戻れないと痛感した.これまでに経験したプログラミング言語と異なる点をピックアップして備忘録的にまとめてみた.Python 3の使用を前提にした Mac OS 12.13.4上での実行であるが,マルチプラットフォーム仕様のためWindows, Linuxとの共有が可能である.

変数

数値や文字列を格納する容器(予約語以外の文字列)を準備し,代入演算子を用いて代入する.

予約語は以下の2行を入力し実行すると表示される33語である

import keyword

print(keyword.kwlist)


['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

演算子

「=」だけではないことに留意する.

代入演算子

a = 5 → 値(5)を変数 a に代入

算術演算子

加算 c=a+b, 減算 c=a-b, 乗算 c=a*b, 除算 c=a/b, 剰余 c=a%b は他の言語と同じ

代入演算子(組み合わせ)

a +=2 → a = a + 2 の意味

a -=2 → a = a- 2 の意味

a *=2 → a = a* 2 の意味

a /=2 → a = a/2 の意味

a **=2 → a = a**2 の意味

比較演算子

a == b

a! = b 等しくなければ「真(true)」,等しければ「偽(false)」を返す演算子

a <> b 等しくない

a >b, a< b, a<=b, a>= b 等

その他

%=, //=, #=, |=, ^=, <<= 等も同じように使うことができる.

入出力

ユーザ入力のために input 関数が用意されている.入力された変数は文字であるので,目的に応じて整数化,実数化が必要である.a+b の処理結果で理解することができる.

# 文字列の入力

a = input('Please input : ')

print('Your input data = ', a)

b = input('Please input : ')

print('Your input data = ', b)

s=a+b

print('s = ', s)


# 整数の入力

a = int(input('Please input : ')) ⬅ input文をint関数で受けている

print('Your input data = ', a)

b = int(input('Please input : '))

print('Your input data = ', b)

s=a+b

print('s = ', s)


# 実数の入力

a = float(input('Please input : ')) ⬅ input文をfloat関数で受けている

print('Your input data = ', a)

b = float(input('Please input : '))

print('Your input data = ', b)

s=a+b

print('s = ', s)


実行結果

Please input : 10

Your input data = 10

Please input : 20

Your input data = 20

s = 1020 ⬅ 文字列の連結


Please input : 10

Your input data = 10

Please input : 20

Your input data = 20

s = 30 ⬅ 整数の加算



Please input : 10

Your input data = 10.0

Please input : 20

Your input data = 20.0

s = 30.0 ⬅ 浮動小数点数の加算


>>>


出力(改行の有無)

print関数を用いる.Python 3ではこれまでと異なり括弧でくくる.

print (x) 出力後,改行される.

print (x, end = "" ) 改行されない


行(1行に複数行が記述できる)

x = 10

y = 20

print (x)

print (y)

上の4行を まとめて表記すると

x, y = 10, 20

print (x,y)

セミコロンを用いれば1行で書くことができる.

x, y = 10, 20; print (x,y)

同じ値を持つものは次のような表記が可能

x = y = z = 100 x,y,z すべて100

x = y = z = 'atom' 文字列も同様に取り扱う

1行が長くなり,行を途中で折り返し,継続したい場合

s = 10 + 20 + 30 + 40 + 50 + 60 + 70 + 80 1 行に書いた文

s = 10 + 20+ 30 + 40 \ 2 行に分けて書く場合 ⬅ Mac の場合, \ は option + ¥ で入力可能.

+ 50 + 60 + 70 + 80


文字列の連結

「“ ”」あるいは「‘ ’」で括られた文字の連結

print ("Good "+ "morning") → 実行結果 Good morning

print ('Good '+ 'morning')でもよい.

次のように書いてもよい.

a = "Good "

b = "morning"

s = a + b

print (s)


数値計算

加算 2+3

減算 5-2

乗算 10*2

べき乗 2 ** 3 → 8

除算 10/2

小数点切り捨て 10 // 3 → 3.0

余り 10 % 3 → 1

優先計算 (2+3)*2


インデント

Pythonに限らず他の言語でも,プログラムの構造を理解しやすくするために,インデント(字下げ)を利用する.CやJavaにおけるインデントは文法的な意味を持っていないが,Pythonにおけるインデントは文法的な意味を持っている.インデント幅が同じ部分がブロックとして処理される.インデントは半角スペースあるいはタブのどちらでもよい.インデントには通常,4個の空白文字を使用する.


条件分岐

if ~ elif ~ else の構文を利用する,入力データに対して,優,良,可,不可を判定して表示するプログラムである.多言語と大きな違いはないが,インデントで enfif のようなステートメントは必要としない.elseif ではなくelif である.ただし,「等しい」は = ではなく,== であり,「等しくない」は != である.

ten = 59

if ten >= 80:

print("Yu")

elif ten >= 70:

print("Ryo")

elif ten>= 60:

print("Ka")

else:

print("Saishi")


対話型処理ならば, 入力した点数を input 関数で受け取り, int で整数化して変数 ten に代入する.


ten = int(input('Tensu?'))

if ten >= 80:

print("優")

elif ten >= 70:

print("良")

elif ten>= 60:

print("可")

else:

print("再試験")

繰り返し

・for文

for i in range(1,10): ⬅ i は1から 9 まで増分1で変化, step 1 は省略可能

print(i)


for i in range(10, 0, -2): ⬅ 10 から 0 まで, step -2 で, 8, 6, 4, 2 と i が減っていく.

print(i*i)

二重ループ

例 九九算

for i in range(1,10):

for j in range(1,10):

print(i * j, end=' ')

print()

i の変化の中に,j の変化を含む例.1から9まで変化させるには,i, j は range(1,10) で範囲を指定する.Pythonでは,for 文の終端を示す next (BASIC), continue (FORTRAN) のような語句は必要としない.その代りにインデントを用いる.行頭の空白文字の数が重要な意味を持ち,同じ数の空白でインデントされた文がブロックとみなされる.

i = 1 の時

J は1 から9まで変化しながら i*j の掛け算を実行する.それが終了すると for j ・・・・と行頭の同じ print() を実行し改行する.

i = 2 の時

同様に計算処理,j=9 まで繰り返す.

実行結果

1 2 3 4 5 6 7 8 9

2 4 6 8 10 12 14 16 18

3 6 9 12 15 18 21 24 27

4 8 12 16 20 24 28 32 36

5 10 15 20 25 30 35 40 45

6 12 18 24 30 36 42 48 54

7 14 21 28 35 42 49 56 63

8 16 24 32 40 48 56 64 72

9 18 27 36 45 54 63 72 81

本例では,桁を揃えるための書式(後述)は使用していない.

・while文

while の後の条件が成立する間,処理を繰り返す.インデントが必要

i = 0

while i < 10:

i = i + 1

print (i)

積算値である1から10までの数値を縦に表示する

1

2

3

4

5

6

7

8

9

10

横に表示させるには end='' を追記する

i = 0

while i < 10:

i = i + 1

print (i , end='')

1から10までの数値を横に表示する

12345678910

i = i + 1 は i += 1と書いてもよい.

i = 0

while i < 10:

i += 1

print (i)

対話型成績処理

n=0

sum=0

while n<100:

ten = int(input('Tensu?'))

if ten < 0: ⬅ 負の値を入力したら終了

break ⬅ 上の条件と合致したら処理を終了し, 人数と平均点を表示する

elif ten >= 80:

print("優")

elif ten >= 70:

print("良")

elif ten>= 60:

print("可")

else:

print("再試験")

n+=1

sum+=ten

print('人数 =',n,'平均 =',sum/n) ⬅ 人数と平均点の出力

BreakとContinue

繰り返し for 文の途中に条件文を置き,条件によって,中断あるいはスキップさせる.breakは繰り返しが終了するのに対し,continueはそれ以降の処理がスキップされるのみで,forループは継続し次の繰り返し処理が実行される.

lst = ['Kumamoto','Nagasaki','Fukuoka','Saga','Ooita','Okinawa','Miyazaki','Kagoshima']

for ken in lst:

if ken == 'Okinawa':

print('Skip!')

continue

print(ken)


書式について

一般的な書式は,format関数を用いる.

'文字列 {} 文字列'.format{変数}

次の実例で理解してほしい

kokugo=82

sansu=75

rika=63

total=kokugo+sansu+rika

print('合計 :{}点'.format(total))

合計 :220点 ← 実行結果

上記の九九算プログラムで桁を合わせるには書式を追加する.


print( "{:2d}{:s}".format(i*j, " "), end='') ← Python 3の書式


{:2d}{:s} 十進数の二桁,文字列を明示している.

print('{:.2}'.format(3.141592))

print('{:.5}'.format(3.141592))

print('{:.5f}'.format(3.141592))

実行結果

3.1

3.1416

3.14159


スライス

スライスを使うと部分文字列の取得が可能である.

文字列オブジェクト[開始インデックス : 終了インデックス]

具体例で説明する.文字列「KUMAMOTO」の英語字を区切っている縦線を以下のように番号付けする.開始インデックス,終了インデックスは部分文字列を挟むように指定する.


0 1 2 3 4 5 6 7 8

| K | U | M | A | M | O | T | O |

[2:5]と指定するとMAMと表示される.

str = "KUMAMOTO"

slice = str[2:5]

print (slice)

MAM ← 実行結果

コメント文

ハッシュ(#)から行末まではコメントとみなされる非実行文.


数学関数

数学関数として,指数関数,対数関数,三角関数,角度変換,双曲線関数,定数等が準備されている.

import math

print(math.sqrt(x)) 平方根

print(math.exp(x)) 指数関数

print(math.log(x, y)) 自然対数

print(math.log10(x)) 常用対数

print(math.sin(x)) 三角関数

math.degrees(x) ラジアンを度に変換

math.pi 定数


例 円周率(π)の近似値を加減乗除と平方根の演算のみで求めるプログラム

import math

t=30; c=0; s=1

for k in range(2,t+1):

c=math.sqrt((1+c)/2)

s=s/2/c

t=s/c

print(k,' ',2**k*s*c,' ',2**k*t)


実行例

2 2.0 3.9999999999999996

3 2.82842712474619 3.3137084989847603

4 3.061467458920718 3.1825978780745277

5 3.121445152258052 3.1517249074292555

6 3.136548490545939 3.144118385245904

7 3.1403311569547525 3.1422236299424564

8 3.1412772509327724 3.1417503691689666

9 3.141513801144301 3.141632080703182

10 3.1415729403670913 3.1416025102568086

11 3.1415877252771596 3.141595117749589

12 3.1415914215111997 3.141593269629307

13 3.1415923455701176 3.141592807599644

14 3.1415925765848725 3.141592692092255

15 3.141592634338563 3.1415926632154085

16 3.1415926487769856 3.1415926559961966

17 3.141592652386591 3.1415926541913946

18 3.141592653288993 3.1415926537401937

19 3.1415926535145933 3.1415926536273937

20 3.1415926535709935 3.141592653599194

21 3.1415926535850938 3.141592653592144

22 3.141592653588619 3.141592653590382

23 3.1415926535895005 3.141592653589941

24 3.1415926535897207 3.141592653589831

25 3.141592653589776 3.1415926535898033

26 3.1415926535897896 3.1415926535897967

27 3.141592653589793 3.141592653589795

28 3.141592653589794 3.141592653589795

29 3.1415926535897944 3.1415926535897944

30 3.1415926535897944 3.1415926535897944

組み込み関数

以下のような関数が準備されている.用途が分からないときは調べればよい.

abs() 絶対値

all()

any()

ascii() 印字可能な表現を含む文字列

bin() 整数を2進数に変換

bool()

bytearray()

bytes()

callable() object 引数が呼び出し可能オブジェクトであれば True を, そうでなければ False を返す.

chr() Unicode コード整数 i である文字を返す

classmethod()

compile() ソースをオブジェクトにコンパイル

complex() 複素数

delattr()

dict() 辞書作成

dir()

divmod()

enumerate()

eval()

exec() Python コードの動的な実行

filter() リストの要素を抽出してくれる関数 実例参照 lambdaとの併用例

float() 浮動小数点数を返す

format() 書式化

frozenset()

getattr()

globals()

hasattr()

hash() オブジェクトのハッシュ値を返す

help() ヘルプシステムの起動

hex() 16進数

id() オブジェクトの "識別値"

input() 入力

int() 整数化

isinstance()

issubclass()

iter()

len() オブジェクトの長さ(要素の数)

list() 関数ではない

locals()

map() リストの要素に演算を適用してくれる関数 実例参照 lambdaとの併用例

max() 最大の要素

memoryview()

min() 最小値

next() 次の要素を取得

object() 新しいオブジェクトを返す

oct() 8進数を返す

open() ファイルのオープン(読み書き用)

ord() chrの逆, 文字のunicodeポイントに対応する数値を与える

pow() xのy乗

print() 書き出し

property() 属性を返す

range() 関数ではない. forの範囲指定, 整数

repr()

reversed() 要素を逆順に取り出す

round() 整数化

set()

setattr()

slice() 部分文字列

sorted() 要素を並べ替え

staticmethod()

str() unicode整数の文字列を返す

sum() 要素の総和

super()

tuple() 関数ではない. 変更不可のシーケンスデータ

type() データ構造 list, tuple, range 等の型を表示

vars()

zip()

__import__()

参考資料

リスト(list) 最重要!

他のプログラミング言語における配列に似たもので,[オブジェクト1, オブジェクト2, ...]のように中括弧内に数値あるいは文字列が括弧で区切られ列んだものである.たとえば,1月から12月までは以下のように記述する.

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

リストオブジェクトは変数に代入することができる.

list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

7番目のデータ(7)を表示させるには,次行を実行すればよい.

print (list[6])

要素の変更

list = [" C", "H", "O"]

list[2] = "S"

print (list)

[' C', 'H', 'S']

新しいリストを代入することで,リストの一部分を別のリストに置き換えることができる.

list = ["C", "H", "O", "N"]

list[2:4] = ["S", "P"]

print (list)

['C', 'H', 'S', 'P']


リストの中のリスト(2次元配列)

以下に示すように, {x,y,z] が一つの要素になり, 繰り返しているリストである. 三次元座標の一点が要素になっているので, 一点を取り出したりするのに便利である. list[2][3]は2番めの三次元座標の3番目すなわちzの値を示す.


[['O', '7.15300', '2.3130', '8.68800'], ['O', '3.40600', '-0.67800', '5.51500'], ['O', '6.71300', '0.20500', '3.39800'], ['C', '5.34000', '0.28700', '6.67200'], ['C', '4.13500', '0.25700', '5.74900'], ['C', '4.04300', '1.65800', '5.19700'], ['C', '4.60300', '2.57500', '6.35400'], ['C', '5.12100', '1.57400', '7.50100'], ['C', '6.54800', '2.05400', '7.68100'], ['C', '7.05500', '', '2.03100', '6.22900']]


[['O', '7.15300', '2.3130', '8.68800'],

['O', '3.40600', '-0.67800', '5.51500'],

['O', '6.71300', '0.20500', '3.39800'],

['C', '5.34000', '0.28700', '6.67200'],

['C', '4.13500', '0.25700', '5.74900'],

['C', '4.04300', '1.65800', '5.19700'],

・]]

要素のソート

sort, reverseを使うとリストに含まれる要素を並べ替えることができる.reverse は逆順,sort は昇順にならべかえる.

ns = [5, 20, 10, 7]


ns.reverse()

print(ns)


ns.sort()

print(ns)


実行結果

[7, 10, 20, 5]

[5, 7, 10, 20]

降順にソートしたい場合は,最初に「sort」を実行してから,次いで「reverse」を実行すればよい.


2次元配列の場合(分子の三次元座標など)

リストが二重になっている二次元配列の場合のリストの並べ替えは lamda関数を使う.

xyz.sort(key=lambda x: x[3])は上記の例では x. y, zのzで座標群を並べ替える.

['H', 8.052, 6.014, 3.101]

['O', 6.713, 0.205, 3.398]

['H', 5.193, 2.385, 3.513]

['C', 7.4, 5.847, 3.771]

['H', 7.622, 3.828, 3.807]

['H', 6.893, 7.778, 4.072]

ListとTuple

ひと塊まりのデータ構造としてlist, tuple, range等がある.tuple は,リストと同じように複数の値を持つことができる.

リストには要素を追加したり,要素を消したりすることができるが,タプルでは原則としてできない(イミュータブル).

listは,中括弧でカンマ区切り,tuple は括弧で表現する.他言語の配列に相当するのがlistである.

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

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


相互変換が可能

l = [0, 1, 2]

print(l)

print(type(l))


t = ('a', 'b', 'c')

print(t)

print(type(t))


u = list(t)

print(u)

print(type(u))

実行結果

[0, 1, 2]

<class 'list'>

('a', 'b', 'c')

<class 'tuple'>

['a', 'b', 'c']

<class 'list'>


rangeも変換可能

r = range(5)

print(r)

print(type(r))

実行結果

range(0, 5)

<class 'range'>

tupleの加算

t = ('a', 'b', 'c')

v = ('d', 'e', 'f')

w = t + v

print(w)

実行結果

('a', 'b', 'c', 'd', 'e', 'f')


タプルの要素切出し

abc = (10, 20, 30)

a, b, c = abc

print(a) --> 10

print(b) --> 20


t = (10, 20, (30, 40, 50))

a, b, c = t

print(a) --> 10

print(b) --> 20

print(c) --> (30, 40, 50)

tupleの一部切出しはsliceでも可能


Range

整数を要素とするイミュータブルなシーケンスを作成するオブジェクトである.

繰り返しfor文における使用が主

range(start, stop[, step])

for i in range(0, 10):

print(i, end="")


print("")


for i in range(0, 10, 2):

print(i, end="")


print("")


for i in range(10, 0, -1):

print(i, end="")


実行結果

0123456789

02468

10987654321

LISTへの追加

リストのメソッドappend()で,末尾に要素を追加することができる.

先頭など,末尾以外の位置に追加したい場合はinsert()を使う.

lst = list(range(3))

print(lst)

実行結果

[0, 1, 2]


lst.append(10)

print(lst)

実行結果

[0, 1, 2, 10]


listは空でもよい


lst = []

print(lst)

実行結果

[]


lst.append(10)

print(lst)

実行結果

[10]


指定位置に要素を挿入

リストのメソッドinsert()で,指定位置に要素を挿入できる.

第一引数に位置,第二引数に挿入する要素を指定.先頭は0,負値の場合,-1が末尾の一つ前となる.

lst = list(range(3))

print(lst)

実行結果 [0, 1, 2]


lst.insert(0, 10)

print(lst)

実行結果[10, 0, 1, 2]


lst.insert(-1, 20)

print(l)

実行結果 [10, 0, 1, 20, 2]

空要素の除去

list = ["red","","orange","","yellow","","green","","brown"]

while "" in list :

list.remove("")

print(list)


実行結果

['red', 'orange', 'yellow', 'green', 'brown']


実例

リスト (data) に含まれる空の要素 ('') を除去するために使用したプログラム.


1. while (True):

try:

data.remove("")

except:

break


2. while '' in data :

data.remove('')


3. data = filter(lambda a: a!='', data) 無名関数を使用すると1行で実現. a!=''は not equal の意味

リストの要素を使った for 文

リスト(配列)などのイテラブルオブジェクトの要素が順番に変数に代入され処理が行われる。すべての要素に対して処理が繰り返される。

lst = ['Kumamoto','Nagasaki','Fukuoka','Saga','Ooita','Miyazaki','Kagoshima']


for ken in lst:

print(ken)

リストの要素数 (n) をlenで知り,n回処理を繰り返すようにする必要はない.


リストを逆順に処理

lst = ['Fukuoka','Saga','Ooita','Nagasaki','Kumamoto','Okinawa','Miyazaki','Kagoshima']


for ken in reversed(lst):

print(ken)

関数の定義 (def~return)

決まりきった仕事は関数として定義して, 随時呼び出して実行することができる. 下記の最小値, 最大値を求めるプログラムの def と return に挟まれた部分である. リスト内の最小値, 最大値に関しては組み込み関数が準備されているのでわざわざ作る必要はない.



#関数定義 最小値と最大値の学習プログラム

a = [6,18,-1,9,19,3,12,14,4,2,13,20,11,15,7,5,16,8,10,17]


def min_dat(a): ⬅ def

minx = a[1]

for i in a:

if i < minx:

minx = i

return minx ⬅ return

print (min_dat(a))


def max_dat(a): ⬅ def

maxy = a[1]

for i in a:

if i > maxy:

maxy = i

return maxy ⬅ return


print (max_dat(a))


実行結果

-1

20


組み込み関数を使用した場合のプログラムは以下の3行


a = [6,18,-1,9,19,3,12,14,4,2,13,20,11,15,7,5,16,8,10,17]

print (min(a))

print (max(a))

#関数定義 並べ替えの学習プログラム


a = [6,18,-1,9,19,3,12,14,4,2,13,20,11,15,7,5,16,8,10,17]


print (a)

n=len(a)

print(n)


def sort_dat(a):

for i in range(0,n+1):

for j in range(i,n):

if a[j] > a[i]:

kari = a[i]; a[i] = a[j]; a[j] = kari

# print (i,j)

return a


print (sort_dat(a))


実行結果

[6, 18, -1, 9, 19, 3, 12, 14, 4, 2, 13, 20, 11, 15, 7, 5, 16, 8, 10, 17]

20

[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, -1]


ここで練習のため作成した「並べ替えプログラム」は「組み込み関数sort」で実現可能である.

lambda 無名関数(これは便利!)

実例で理解した方が早い. 組み込み関数 filtrやmap と組み合わせることにより一括処理が可能になる.


例1 以下の例では,lambda式を使って引数を計算処理しリストに代入している.

import math

lst=[1, 2, 3, 4, 5]

lst2=list(filter(lambda x: x%2==0, lst)) ⬅ 除算の結果がゼロになる数値をリスト全要素にについて調べて,その結果を新リストに書き込む.

print (lst2)


import math

lst=[1, 2, 3, 4, 5]

lst2=list(map(lambda x: x**2, lst)) ⬅ 自乗の計算をリスト全要素にについて行い,その結果を新リストに書き込む.

print (lst2)


lst=[1, 2, 3, 4, 5]

lst2=list(map(lambda x: math.sqrt(x), lst)) ⬅ 平方根の計算をリスト全要素にについて行い,その結果を新リストに書き込む.

print (lst2)


lst=[1, 2, 3, 4, 5]

lst2=list(map(lambda x: int(math.sqrt(x)), lst)) ⬅ 上の結果を整数化して新リストを作成

print (lst2)


実行例

[2, 4]

[1, 4, 9, 16, 25]

[1.0, 1.4142135623730951, 1.7320508075688772, 2.0, 2.23606797749979]

[1, 1, 1, 2, 2]



例2 熊本の月別平均雨量データがリストで与えられている. 一つの要素は月と雨量を含んでいる場合, 雨量でソートしたい場合, Lambda を使うと簡単に実行できる.


rainLst = [['1月',60.1], ['2月',83.3], ['3月',137.9], ['4月',145.9], ['5月',195.5], ['6月',404.9], ['7月',400.8], ['8月',173.5], ['9月',170.4], ['10月',79.4], ['11月',80.6], ['12月',53.6]]

print(rainLst)

print()

sortedrainLst = sorted(rainLst, key=lambda x: x[1]) ⬅ x[1]は雨量でソートすることを示している

print(sortedrainLst)


実行結果

[['1月', 60.1], ['2月', 83.3], ['3月', 137.9], ['4月', 145.9], ['5月', 195.5], ['6月', 404.9], ['7月', 400.8], ['8月', 173.5], ['9月', 170.4], ['10月', 79.4], ['11月', 80.6], ['12月', 53.6]]


[['12月', 53.6], ['1月', 60.1], ['10月', 79.4], ['11月', 80.6], ['2月', 83.3], ['3月', 137.9], ['4月', 145.9], ['9月', 170.4], ['8月', 173.5], ['5月', 195.5], ['7月', 400.8], ['6月', 404.9]]


逆ソート

rainLst = [['1月',60.1], ['2月',83.3], ['3月',137.9], ['4月',145.9], ['5月',195.5], ['6月',404.9], ['7月',400.8], ['8月',173.5], ['9月',170.4], ['10月',79.4], ['11月',80.6], ['12月',53.6]]

print(rainLst)

print()

sortedrainLst = sorted(rainLst, reverse=True, key=lambda x: x[1])

print(sortedrainLst)

実行結果

[['1月', 60.1], ['2月', 83.3], ['3月', 137.9], ['4月', 145.9], ['5月', 195.5], ['6月', 404.9], ['7月', 400.8], ['8月', 173.5], ['9月', 170.4], ['10月', 79.4], ['11月', 80.6], ['12月', 53.6]]

[['6月', 404.9], ['7月', 400.8], ['5月', 195.5], ['8月', 173.5], ['9月', 170.4], ['4月', 145.9], ['3月', 137.9], ['2月', 83.3], ['11月', 80.6], ['10月', 79.4], ['1月', 60.1], ['12月', 53.6]]

二次元配列の列方向の最小値,最大値を求める

原子種, x座標, y座標, z座標からなる要素(分子の原子座標)の中から特定の座標について, 最小値, 最大値を含む要素を抽出する. 組み込み関数のみで計算する方法.


axyz=[['O','16.753116','-0.874840','5.434024'],

['C','15.707677','-0.337043','5.684668'],

['C','14.492358','-0.952449','6.348298'],

['C','13.375906','-0.184082','5.652743'],

['C','13.852066','0.958845','5.136511']]


xmin=min(axyz, key=(lambda s: s[1])) ⬅ リストaxyzのX座標の最小値を有する要素

print(xmin)

xmax=max(axyz, key=(lambda s: s[3])) ⬅リストaxyzのZ座標の最大値を有する要素

print(xmax)


実行結果


['C', '13.375906', '-0.184082', '5.652743']

['C', '14.492358', '-0.952449', '6.348298']

ファイル入出力

オープン

変数 = open(‘オープンするファイルの名前’, ‘オープン様式’)

r 読み込みモードで開く ファイルが存在しない時はエラー

w 書き込みモードで開く ファイルが存在しない時は新規作成

a 追加書き込みモードで開く ファイルが存在しない時は新規作成

r+ 読み書き両対応で開く ファイルが存在しない時はエラー

w+ 読み書き両対応で開く ファイルが存在しない時は新規作成

a+ 追加書き込み・読み書き両対応で開く ファイルが存在しない時は新規作成


ファイルの読み込み

file = open('aaa.txt', 'r') #読み込み様式

abc = file.read() #readですべて読み込む

print(abc)


file = open('aaa.txt', 'r') #読み込み様式

abc = file.readline() #readlineで1行読み込む

while abc:

print(abc)

abc = file.readline()


file = open('aaa.txt', 'r') #読み込み様式

abc = file.readlines() #readlinesでリストとして読み込む

print(abc)


ファイルへの書き込み

file = open('aaa.txt', 'w') #書き込み様式でオープン

abc= 'Happy New Year'

file.write(abc) #プログラムが保存されている場所に新規ファイルが作られる

実行結果 Happy New Year

file = open('aaa.txt', 'w') #書き込み様式でオープン

abc_list = ['Happy', ' ', 'New', ' ', 'Year'] #リストの書き込み

file.writelines(abc_list)

実行結果 HappyNewYear

file = open('aaa.txt', 'a') #追加書き込み様式でオープン

abc_list = ['Merry', 'Christmas'] #既存ダータに追記

file.writelines(abc_list)

実行結果 HappyNewYearMerryChristmas

ファイルのクローズ

file.close() #ファイルをクローズ

日時

日時は以下の例で示す方法で取得することができる.

import datetime


print (datetime.date.today()) #実行結果 2018-06-14


print (datetime.datetime.now()) #実行結果 2018-06-14 09:08:57.836495


now = datetime.datetime.today()

print (now.strftime("%Y/%m/%d")) #実行結果 2018/06/14


print (datetime.datetime.today().strftime("%Y.%m.%d")) #実行結果 2018.06.14


実行時間の計測

time(clock)を用い,実行前後の時間差から求めることができる.I が1から10万までの平方根の計算が 0.028 秒であることがわかる.

import math

import time

time1 = time.clock()

for i in range(100000):

a = math.sqrt(i)

# print(a)

time2 = time.clock()

print (time2 - time1)


実行結果

0.026055999999999996 (CPU core i5)

グラフィックス

タートルグラフィックス

タートルグラフィックスは Wally Feurzig と Seymore Papert が 1966 年に開発した Logo プログラミング言語の一部であり,子供にプログラミングを教えるために使用されてきた.次図に示す亀を動かすことによって得られる軌跡を使って作図をすることができる.




最大限拡大した亀の図

タートルグラフィックスの紹介で定番の tree 使って描いてみた.

描画速度は speed()で指定する.ゼロが最高値.

注意事項 Pythonのグレードアップ中に turtle が動かなくなるトラブルが発生した,試行錯誤の結果,古いPythonのturtle関連の「turtle???.pyc」ファイルを削除したら正常に描画できるようになった.

エラーメッセージ:Python3 turtle ImportError: bad magic number in 'turtle'

matplotlib

matplotlibPythonでグラフを描画するときなどに使われる標準的なライブラリである.画像ファイルばかりではなく,簡単なアニメーションを作ることも可能である. 実例はmatplotlibサイトのmatplotlib/galleryで見ることができる.

描画するデータの作成には,プログラミング言語Pythonにおいて数値計算を効率的に行うための拡張モジュールであるnumpyを利用すると便利できる.サインカーブを描く時は範囲を与えるだけでよい.

WIndowsではインストールエラー発生

Matplotlibライブラリインストール時に「error: Microsoft Visual C++ 14.0 is required.」エラーが発生した.

環境 OS: Windows 10 ,python: 3.7.0

2018.07.01 現在 エラーメッセージに表示されるアドレスからは必要なインストーラがダウンロードできないが,以下のURLより直接ダウンロードできる.https://download.microsoft.com/download/5/F/7/5F7ACAEB-8363-451F-9425-68A90F98B238/visualcppbuildtools_full.exe

numpy(数値計算ライブラリ)

数値計算を効率的に行うための拡張モジュールである numpy を利用すると, 「決まりきった計算処理」を1行で書くことができる. 以下は最小値,最大値,合計,平均,標準偏差を求める処理を含むプログラムの例である.

最小値,最大値,合計.平均,標準偏差など

k=1

array=[] ⬅ 空のリストを準備

array1=[]

while k<100: ⬅ 繰り返し文, 100人まで入力可能

ten = int(input('Tensu?')) ⬅ データはキーボードから入力

if ten < 0: ⬅ 負のデータで入力終了

break

elif ten >= 80:

array1.append("優") ⬅ リストへの成績(評価)を追加

elif ten >= 70:

array1.append("良")

elif ten>= 60:

array1.append("可")

else:

array1.append("再試験")

array.append(ten)

print('')

print(array)

print(array1)

print('')


#組み込み関数

n=len(array) #リストのデータ数

print('人数 =',n)

print('組み込み関数で求られる値')

print('最小 =',min(array))

print('最大 =',max(array))

print('合計 =',sum(array))

print('')


for i in range(0, n):

print(i+1, array[i], array1[i])

print('')

#numpy.ndarrayの場合

print('Numpy配列に変換して計算処理')

import numpy as np

arr_ten = np.array(array)


print(arr_ten)


print('人数 =',n)

print('最小 =',np.min(arr_ten))

print('最大 =',np.max(arr_ten))

print('合計 =',np.sum(arr_ten))

print('平均 =',np.mean(arr_ten))

print('標準偏差 =',np.std(arr_ten))


import matplotlib.pyplot as plt #棒グラフ描画

left = np.array(range(1,n+1))

height = np.array(arr_ten)

plt.bar(left, height)

plt.show()



実行結果

Tensu?61

Tensu?72

Tensu?85

Tensu?65

Tensu?43

Tensu?70

Tensu?59

Tensu?35

Tensu?94

Tensu?63

Tensu?-1


[61, 72, 85, 65, 43, 70, 59, 35, 94, 63]

['可', '良', '優', '可', '再試験', '良', '再試験', '再試験', '優', '可']


人数 = 10

組み込み関数で求られる値

最小 = 35

最大 = 94

合計 = 647


1 61 可

2 72 良

3 85 優

4 65 可

5 43 再試験

6 70 良

7 59 再試験

8 35 再試験

9 94 優

10 63 可


Numpy配列に変換して計算処理

[61 72 85 65 43 70 59 35 94 63]

人数 = 10

最小 = 35

最大 = 94

合計 = 647

平均 = 64.7

標準偏差 = 16.59548131269473


回帰直線

回帰直線を求めるプログラムの例である.分散,標準偏差,相関係数に加えて,一次式の勾配と切片等の計算処理をそれぞれ1行で書くことができる.

import numpy as np

from matplotlib import pyplot as plt

x = np.array([1,2,3,4,5])

y = np.array([2.1,3,4,5,7])


plt.scatter(x,y) # 入力データをそのままプロット

print('var for x =', np.var(x)) # np.var 分散の計算

print('var for y =', np.var(y))

print('std for x =', np.std(x)) # np.std 標準偏差の計算

print('std for y =', np.std(y))

print('r =',np.corrcoef(x, y)[0, 1]) # np.corrcoef 相関係数


print('a&b',np.polyfit(x, y, 1)) # polyfitは次数1の場合一次式 ax+b の係数を返す

y=np.poly1d(np.polyfit(x, y, 1))(x) # poly1dは係数 a、b をもとにy値を生成


plt.plot(x,y) # 回帰直線のプロット

plt.show()

乱数

import numpy.random as rd

x = rd.rand(3, 5) ⬅ 3行5列

print (x)


実行結果

[[0.25440123 0.40478737 0.96078514 0.40123151 0.17013309]

[0.92499464 0.96364692 0.86116582 0.87724377 0.06284516]

[0.91616984 0.29506346 0.95762294 0.6012564 0.56678873]]

乱数による π の計算


import math

from numpy.random import *


n=0

t=int(input('Please input:'))

for i in range(1,t):

x=rand()

y=rand()


l=math.sqrt(x*x+y*y)

if l<=1.0:

n=n+1

print(n*4/t)


実行結果

Please input:100000

3.14812

2個の乱数で求めた x, y 座標をプロットして,原点からの距離が1.0以下の点(円内に存在する赤点)の存在確率からπが求められる.

実行結果

================== RESTART: /Users/KH/pythonPRG/numpy_Pi.py ==================

Please input:1000

3.184

>>>

================== RESTART: /Users/KH/pythonPRG/numpy_Pi.py ==================

Please input:10000

3.1648

>>>

================== RESTART: /Users/KH/pythonPRG/numpy_Pi.py ==================

Please input:100000

3.14408

>>>

================== RESTART: /Users/KH/pythonPRG/numpy_Pi.py ==================

Please input:1000000

3.140424

>>>

================== RESTART: /Users/KH/pythonPRG/numpy_Pi.py ==================

Please input:10000000

3.1414808

>>>

参考資料 Scratch言語で作った円周率プログラム

分子構造描画

手元にあったcubaneの三次元座標をファイル(空白区切り)から読み込み,1列目の原子番号,2, 3, 4列目のx座標,y座標,z座標をそれぞれのリストに呼び込み作図を試みた.投影軸に沿って原子を並べ直し,奥の方から原子を描く手順は今回は考慮していない.

C -2.1434 3.2205 -0.7607

C -3.3430 2.9171 0.2166

C -1.1232 2.9776 0.4164

C -2.3227 2.6737 1.3934

C -1.0470 1.4497 0.0353

H -0.2715 3.6101 0.6480

C -2.2466 1.1461 1.0121

H -2.4239 3.0636 2.4018

C -3.2668 1.3891 -0.1651

H -4.2555 3.5010 0.2884

H -2.2876 0.3210 1.7167

C -2.0673 1.6928 -1.1420

H -4.1189 0.7571 -0.3963

H -0.1345 0.8657 -0.0369

H -2.1025 4.0451 -1.4660

H -1.9661 1.3028 -2.1504

a,x,y,z = [], [], [], []

for line in open('cubaneCH.txt').readlines(): #リストとして読み込む

data = line[:-1].split(' ')

print(data)

a += [data[1]] #a.append(int(data[1]))

x += [float(data[2])]

y += [float(data[3])]

z += [float(data[4])]


print(a);print(x);print(y);print(z)


n=len(a)

print(n)


import math

from turtle import *

resetscreen()

setworldcoordinates(-5,-5,5,5)

speed(0)

pensize(2)

penup()

zmin=min(z);zmax=max(z);sa=zmax-zmin

print(sa)

for i in range(0,n):

for j in range(i,n):


d=math.sqrt((x[i]-x[j])**2+(y[i]-y[j])**2+(z[i]-z[j])**2)

if d> 1.0 and d<1.8:

print(i,j,d)

penup()

goto(x[i],y[i])

pendown()

goto(x[j],y[j])

elif d < 0.1:

goto(x[i],y[i])

if a[i] == 'H':

#pencolor('cyan')

pendown()

dot(2*(sa+z[i]),'cyan')

else:

pendown()

#pencolor('black')

dot(5*(sa+z[i]),'black')

penup()


hideturtle()


XY座標を用いて描いたcubane分子

奥行き(z軸)を考慮して原子の大きさを変え擬似的に立体感を出してみた.

計算結果を表示させた結果

================= RESTART: /Users/KH/pythonPRG/readcoord.py =================

['', 'C', '-2.1434', '3.2205', '-0.7607']

['', 'C', '-3.3430', '2.9171', '0.2166']

['', 'C', '-1.1232', '2.9776', '0.4164']

['', 'C', '-2.3227', '2.6737', '1.3934']

['', 'C', '-1.0470', '1.4497', '0.0353']

['', 'H', '-0.2715', '3.6101', '0.6480']

['', 'C', '-2.2466', '1.1461', '1.0121']

['', 'H', '-2.4239', '3.0636', '2.4018']

['', 'C', '-3.2668', '1.3891', '-0.1651']

['', 'H', '-4.2555', '3.5010', '0.2884']

['', 'H', '-2.2876', '0.3210', '1.7167']

['', 'C', '-2.0673', '1.6928', '-1.1420']

['', 'H', '-4.1189', '0.7571', '-0.3963']

['', 'H', '-0.1345', '0.8657', '-0.0369']

['', 'H', '-2.1025', '4.0451', '-1.4660']

['', 'H', '-1.9661', '1.3028', '-2.1504']

['C', 'C', 'C', 'C', 'C', 'H', 'C', 'H', 'C', 'H', 'H', 'C', 'H', 'H', 'H', 'H']

[-2.1434, -3.343, -1.1232, -2.3227, -1.047, -0.2715, -2.2466, -2.4239, -3.2668, -4.2555, -2.2876, -2.0673, -4.1189, -0.1345, -2.1025, -1.9661]

[3.2205, 2.9171, 2.9776, 2.6737, 1.4497, 3.6101, 1.1461, 3.0636, 1.3891, 3.501, 0.321, 1.6928, 0.7571, 0.8657, 4.0451, 1.3028]

[-0.7607, 0.2166, 0.4164, 1.3934, 0.0353, 0.648, 1.0121, 2.4018, -0.1651, 0.2884, 1.7167, -1.142, -0.3963, -0.0369, -1.466, -2.1504]

16

4.5522

0 1 1.576771070891396

0 2 1.5765065366182283

0 11 1.5764035619091958

0 14 1.0858572926494527

1 3 1.5764244003440189

1 8 1.5767959062605408

1 9 1.0857028599022842

2 3 1.576605359625547

2 4 1.5765538557245673

2 5 1.0858580478128805

3 6 1.5763066516385702

3 7 1.0858793717536033

4 6 1.5764997177291216

4 11 1.5767514039949353

4 13 1.0857831689614643

6 8 1.5765966129609692

6 10 1.085786429276034

8 11 1.57650485251394

8 12 1.0857954917939197

11 15 1.0859152821468163


実際に合成した54原子のカゴ型分子を描いてみた.

Canvasによるグラフィックス

Python言語には,画面上にボタン等を配置し,操作することを可能にするGUIインターフェースを作成するツールキット「Tkinter」が備わっている.そのTkinterを使ってキャンバスに図形を描くことができる,

基本画像

create_line 線分、折れ線、曲線

create_rectangle 矩形(くけい)

create_polygon 多角形

create_oval 楕円

create_arc 円弧

create_text 文字列

create_bitmap 画像(2 色)

create_image 画像(カラー)

create_window 窓


fill = 色 内部を塗りつぶす色

stipple = ビットマップ 内部を塗りつぶすときの模様になるビットマップ

outline = 色 枠の色

width = 幅 枠の幅(デフォルトは 1.0)

基本構文は次例で示すとおりである.赤丸を描く行を書き加えるだけで日の丸を描くことができる.

from tkinter import *

root = Tk()

canvas = Canvas(root, width = 460, height=330)

canvas.create_oval(160, 90, 300, 230, fill='red') ⬅

canvas.pack()

root.mainloop()

描画に関する文法の詳細を理解するには,既存のスクリプトをコピー・ペーストして実行してみるのが早道である.プログラムは何でもよい.私は,愛知大学経済学部の有澤健治先生によるテキスト「Pythonプログラミング」の第3章に紹介されているデモプログラムを使用した.各種設定値を変更して実行し,描画結果を比較して学習したところ,スピーディにマスターすることができた.

本プログラムには画面上部にメニューが設けられている.ボタンを押せば印刷,画面消去ができる.そのような機能も作成することが可能である.

from tkinter import * ⬅必須項目

import sys

def pr(): ⬅関数定義 メニュー対応

d=c.postscript(file="a.eps")

def quit(): ⬅関数定義 メニュー対応

tk.destroy()

tk=Tk()

f=Frame(tk)

b1=Button(f,text='write canvas to a.eps', command=pr)

b1.pack(side='left',expand=YES,fill='x')

b2=Button(f,text='quit',command=quit)

b2.pack(side='right',expand=YES,fill='x')

f.pack(fill='x')

# --- Canvas starts from this line --- ⬅ 図と対応する部分

c=Canvas(width=500,height=350,background='cyan') ⬅ キャンパスの大きさと背景色の指定

c.pack()

c.create_rectangle(2,2,490,340);#The maximum rectangle we can draw. ⬅ 外枠(細い線)

c.create_line(230,150,350,160) ⬅ 中央の線

c.create_rectangle(75,30,175,80,outline='blue') ⬅左上の長方形(外枠 青)

c.create_rectangle(100, 50, 200,100,fill='#F00') ⬅左上の長方形(赤塗りつぶし)


c.create_polygon(300,200,350,260,250,260,fill='yellow',width=2,outline='black') ⬅ 三角形


c.create_oval(100, 200, 200,250,outline='brown',width=30) ⬅ ドーナツ


c.create_oval(380, 50, 440,110,outline='red',width=2) ⬅ 円(赤枠)

c.create_oval(380, 150, 440,210,outline='red',width=2,fill='red') ⬅ 円(赤塗りつぶし)

c.create_arc(250,30,350,80,start=90,extent=245,width=3,fill='pink') ⬅ 円(ピンク部分円)


c.create_text(220, 100,text='Kumamoto',font='Times 30 bold italic',anchor='nw')

c.create_text(10,10,text='0',font='Courier 12') ⬅ 左上隅 原点表示

c.create_line(20,10,360,10,arrow='last') ⬅ 上部 横線(→)

c.create_text(370,10,text='x',font='Courier 12') ⬅ 上部 横線xの表示

c.create_line(10,20,10,270,arrow='last') ⬅ 左側 縦線(↓)

c.create_text(10,280,text='y',font='Courier 12') ⬅ 左側 横線yの表示

c.create_line(100,150,130,180,160,150,190,180,220,190,250,175,300,190,smooth=YES,width=5,fill='blue', arrow='last') ⬅ 複数の点を通るスムースな曲線を描く

for n in range(0,25):

c.create_line(30,100+5*n,50,100+5*n) ⬅ 幅広点線

for n in range(0,13):

c.create_text(100+25*n,280,text=n,font="Osaka 14",anchor="n") ⬅ 0から12までの数値を描く

tk.mainloop() ⬅描画状態を維持するために必要


Canvas グラフィックスを使って分子描画プログラムを作ってみた.先に紹介したTurtle グラフィックスのそれと比較すると圧倒的に描画速度が速い.


コンパイル

Pythonの場合,プログラムを作成する過程はインタプリタで十分である.自分用のプログラムの場合なら,ライブラリの速度が速いのでインタプリタでも速度に不満を感じることはない.しかし,プログラムの中身を見られたくないとか,出来ることならもっと速くしたいという場合はコンパイルすればよい.そのためのツールとして,pyinstaller準備されている.Pyinstallerは,他のモジュールと同様に pip install pyinstaller でインストールすればよい.

コンパイルするには,基本的には以下を実行する.

pyinstaller test.py

オプションについては,結果を1ファイルにまとめるために --onefile を用いる程度でよい.生成したファイルはdist (Windowsは__pycache_)というフォルダに保存される.ダブルクリックするとファイル情報をみると,unix実行ファイルとなっている.

実際に使った感じでは,グラフィックにturtleを使用したプログラムではコンパイルは成功するが,実行時にエラーが出るようである.Matplotlibを使用したサインカーブの描画プログラムはwindows PC環境でも問題なく動いた.

関連して掲載したブログ

Python独習資料(大学,講義資料)

Pythonプログラミング 数値計算ライブラリによる短縮化(最小二乗法)

Pythonプログラミング(IT)

参考資料

turtle — タートルグラフィックス

SciPy - NumPyを基盤にした科学計算ライブラリ

Matplotlib, a plotting package based on NumPy

Python チュートリアル