Pythonの基礎

1.Python(パイソン)について

(1)Pythonとは

・Pythonは、ニシキヘビの意味らしく、ロゴも蛇が2匹である。
・バージョン 2.x代と3.0代では大きく違う
現在では、Python3.6か3.7を使うだろう
 ・攻撃コード(PoCコード)などはPythonで書かれることが多い。セキュリティ系のエンジニアはPythonを使うことがよくある。
・Googleのサービスでは主にPythonで書かれている。AIでも活用されている。
・Pythonは手続き型のCとは異なり、オブジェクト指向型の言語です。これは、Javaと同じなのですが、Javaは基本はコンパイルしますが、
VBScriptやJavascriptなどのように、スクリプト言語です。※スクリプト言語の方がわかりやすくて便利ですよねー。
・Cなどに比べてシンプルな構文になっているので、初心者でもわかりやすい言語かもしれない。
・感覚でしかないが、Javaの半分以下で書けると思う。→習得も早い
 ・Pythonは基本はLinuxで使いましょう。Windowsでも使えるが、モジュールなどが不十分だったりする。
・解説は以下がありがたい。
http://www.tohoho-web.com/python/index.html
・Python公式ドキュメントは以下
https://docs.python.org/ja/3/

(2)言葉や基本的なこと

❶言葉
・ネスト(入れ子):たとえば、ループの中にループを作ったり、関数の中に関数を作る
❷複数の命令をつなげるには ; を使う

a=1
b=2
c=3

これは、以下と同じ

a=1;b=2;c=3

❸コメント
・1行コメントは #をつける
・複数行の場合は、ダブルクォート3つ """ または シングルクォート 3つ ''' で囲う

"""
この2行はコメント
作者:user1 作成年月日:2020.1.1
"""
data1 = 'hello'  #ここはコメント
#以下はdata1の中身を表示する。これもコメント
print(data1)

❹リテラルと定数
・リテラルは、まずは「値」のこと、と考えよう。たとえば、x=5の5という値や、x='Hello'のHelloという文字がリテラルである。
・リテラルは型を持ち、上の5というのは整数型(?)のリテラルで、Helloというのは文字型(?)のリテラル。
・リテラル(literal)とは、「文字の」とか「文字通り」という意味です。
・例が正しいかは分からないが、2行目のprintは、ageをいう文字通りを出力している文字列リテラル。(※ちょっと怪しい)

age='25'
print('age') # ==> age 文字列リテラル。ageという文字を出力
print(age)   # ==> 25 変数 ageの値である25を出力

定数もリテラルみたいなものであるが、意味するものが違う。
age='25' において、ageが定数、25という値がリテラル

(3)コードの書き方

・改行はプログラムの終わりを意味する。ただ、[]や{}、()でくくられたものは、途中で改行が可能。
・可読性の高いコードとして、PEP8と呼ばれる「Style Guide for Python Code」が発表されている。
https://www.python.org/dev/peps/pep-0008/
たとえば、+などの演算子の前後には半角スペースを入れるとういうもの。
・コードをチェックしてくれるサイトもある。便利だ。
http://pep8online.com/
・自動修正も可能だと思う。
http://trelab.info/visual-studio-code/python-vscode%E3%81%A7autopep8%E3%82%92%E9%81%A9%E7%94%A8%E3%81%99%E3%82%8B/
・たとえば、以下のプログラムを見てみよう。(修正前)

moji = "モジ"
atai = 123
print("文字=%s,値= %d" %(moji,atai)) 

上記のサイトでチェックすると、いくつかのメッセージが出る。スペースを入れるなどの修正をすると、以下。

moji = "モジ"
atai = 123
print("文字= %s ,値= %d " % (moji, atai))
(4)自分へのアドバイス

・forでいくつも回さない
・インデントはツールに任せる
はリスト、()は関数の値なので、appendの場合は()かかどっち? そう考えれば理解が進む。

2.print 文字を表示する

(1)単純な文字列の表示

❶表示してみよう
文字列は"で囲うでもいいし、表記はいろいろある。javaでは、1文字は''、文字列は""と区別されていましたが、pythonでは区別されていません。このあたり、適当に覚えていても動いてくれるからありがたい。
print 'hello'
print("hello1")
print('hello2')

それ以外にも、いろいろと試してみるといいですよ。
参考までに、いくつか試した結果が以下です。
print("12") →12
print(12) →12
print(こんにちは) →エラー
print("こんにちは') →エラー

❷Linuxにて、日本語を表示する場合
文字コードでエラーが出る場合があるので、以下を入れておきましょう。
# -*- coding: utf-8 -*-

#!/usr/bin/python
# -*- coding: utf-8 -*-
print 'hahaはhello'
print("h文字ello1")
print('h文字ello1')

❸改行を含めて表示する場合
ダブルクォーテーション3つ「"""」で囲います。
print("""ab
 cde
 fg""")

❹エスケープシーケンス ~特殊な文字を表示する場合
たとえば、「'」を表記する場合には「¥」を付けます。英語のキーボードでは「\」(バックスラッシュ)と表現されることでしょう。これを付けないと、プログラム的な意味なのか、単なる文字列なのかが分からないからです。
print ('こん\'ちくは')
こん'ちくは

// /は無効化しているので、/を意味する
/' 上と同じで’を意味する。
/n 改行
/t タブ
"""で記載すると、コメントになるが、そのあとに書いた文字の改行がそのまま使われる。

また、"と'を両方使うという手もある。そうすれば、エスケープシーケンスは不要だ。
>>> print("This is 'MINE'")
This is 'MINE'
❺エスケープシーケンス2 raw文字列(raw strings)
rをつけて、エスケープシーケンスではなく、文字をそのままとして認識する
実際にやってみる。

print('C:\home\name1user')
print(r'C:\home\user1')

以下のように、rをつけると、\nがエスケープシーケンスではなく、文字として認識される。

C:\home
ame1user
C:\home\user1
(2)変数の値を表示

❶変数そのもの
変数だけなら、なんてことはない。print() に変数名を入れるだけ。

data1 = 'hello'
print(data1)

・実行結果は以下

hello

❷変数の指定した番目の文字 今回は2番目の文字

word = 'hello'
print(word[1]) #==> e

❸入力した文字に加えて、変数を出す
ちょっと工夫が必要で、C言語みたいに、変数の型に応じた表示が必要。
string(文字列)型は%s、int型は%d
構文としては、' ' で入力したい文字を囲うが、変数の場合は上記に書いたように%s、%dをつける。そして、その後、%をつけたあと()で変数名を入れる。
・以下は、直接入力した文字(msg=)と変数の値を組み合わせて表示する。

data1 = 'hello'
print('msg=%s' % (data1))

・実行結果は以下

msg=hello

・両方を組み合わせた例

moji="モジ"
atai=123
print("文字=%s,値=%d" %(moji,atai)) 

・formatメソッドを使う  ※おすすめ

moji="モジ"
atai=123
a='文字={},値={}'.format(moji,atai)
print(a) #==>文字=モジ,値=123

formatに関しては、奥が深い。以下も参照
https://gammasoft.jp/blog/python-string-format/
・全てが文字であれば、表記は簡単で、以下のようにできる。今回はstr()で数字を文字に変換している。

moji="モジ";atai=123
print("文字=" + moji + ",値=" + str(atai)) 

・「,(カンマ)」で区切れば、比較的簡単に表記できるが、変数の前後に空白スペースが入ってしまう。

moji="モジ";atai=123
print("文字=",moji,",値=",atai)   #==> 文字= モジ ,値= 123

・ベタではあるが、;で命令を分けてもいい。こんな感じ。

moji="モジ";atai=123
print('文字=',end="");print(moji,end="");print(',値=',end="");print(atai)

❹改行を無しにする
printで、end=''とする。シングルクォートではなく、ダブルクォート2つでもOK→””

for i in range(5):
    print(i,end="")

結果は以下

01234

3.文字列の処理

(1)文字列の処理の基本

❶文字の連結
以下のように、そのまま足したりという四則演算ができる。引き算はできない。
>>> word1 = 'hel'
>>> word2 = 'lo'
>>> text = word1 + word2
>>> print(text)
hello

・文字の掛け算もできる。
>>> print(text*2)
hellohello

❷検索
・文字が含まれているかという単純なのであれば、以下でいい。helloの中に、loがあるかを検索する。
>>> print('lo' in 'hello')
True

❸文字列を指定された位置で抜き出す(スライス)
・数字だけを指定すると、その位置の文字を表示する
・先のスライスでも書いたが、スライスによって、文字列を指定された位置で切ることができる。

word = "Wordlist"
print(word[2])  # ==> r 
print(word[-1]) #一番最後という意味。なので、print(word[7])と同じ 
print(word[0:3]) # ==> Wor  1文字目から3文字目(★終わりは3文字目というのがややこしい。一つ手前まで、と考えるといいのかも)
print(word[1:3]) # ==> or   2文字目から3文字目 print(word[1:-5]) と同じ
print(word[:]) # ==> Wordlist   すべての文字
print(word[:3]) # ==> Wor   3文字目まで
print(word[10]) #==>エラー IndexError: string index out of range
print(word[10:])  #==> エラーにならない。もちろん、結果は何も出ない。値が無いので
print(word[10:20]) #==> エラーにならない。もちろん、結果は何も出ない。値が無いので

・範囲を指定して表示する場合。
[開始位置, 終了位置, 間隔]
以下は、2文字目から10文字目までを3文字間隔で取得

moji='pythonnobenkyou'
print(moji[2:10:3]) #==>tnb

・文字だけでなく、配列などにも使える。その場合、文字数ではなく、配列の個数でカウントされる。

x='1234567890abcdefg'
print(x[:3]) #==> 123
y=['123','456','789','abc','def']
print(y[:3]) #==> ['123', '456', '789']
z=[[0,1,2],[10,11,12],[20,21,22],[30,31,32]]
print(z[:3]) #==>[[0, 1, 2], [10, 11, 12], [20, 21, 22]]
(2)文字列処理のメソッド

❶文字列の置換 replace
文字列の置換 以下は、カンマを削除している。

price = '1,980'
print(price.replace(',', '')) #==>1980

・最大置換回数を指定する場合は、数字をつける
以下は、sを2回Sに変換する。

word='assemble essay'
print(word.replace('s', 'S',2)) # ==> aSSemble essay

❷文字を区切る split()、結合するjoin
文字を区切って、配列に入れることができる。

data = 'red,bule,green'
data2=data.split(',')
print(data2)  #==> ['red', 'bule', 'green']

・配列になっているので、データ処理も楽になる。

print(type(data2))    # ==><class 'list'>
print(data2[0])         # ==> red

・区切った文字を別々の変数に入れるなら以下。

data = 'red,bule,green'
data1,data2,data3=data.split(',')
print(data1,data2,data3)  #==> red bule green

・逆に結合する場合はjoinを使う。構文としては、 「結合時の区切り文字.join(リスト)」

print(':'.join(data2))  # ==> red:bule:green

❸文字列の検索 find()
検索する文字が、何番目にあるかを示す。ただ、最初の文字しか出ない。

data = 'red,bule,green'
data2=data.find(',')
print(data2) #==>3

❹数のカウント  count
以下のようにして、文字列にある特定の文字の数をカウントできる。

data = 'red,bule,green'
data2=data.count(',')
print(data2)  #==> 2

・タブの数を数えるなら、\tとする

print(x.count('\t'))

❺大文字小文字
・lower→文字を小文字にする
・upper →大文字に
・capitalize →先頭を大文字に
以下に、これまでのを含めて文字の置換を紹介する

x=' I am a boy. ' 
x.strip() #==>'I am a boy.' 両方の空白を消す
x.rstrip() #==>' I am a boy.' right(右)の空白を消す
x.lstrip() #==>'I am a boy. ' left(左)の空白を消す
x.replace(' ','') #==>'Iamaboy.' 空白を''に置き換える
x.lower() #==>'  i am a boy. ' 小文字にする
x.upper() #==>' I AM A BOY. ' 大文字にする
x.split() #==>['I', 'am', 'a', 'boy.']
x.strip().capitalize() #==>'I am a boy.' 空白を消してから、先頭を大文字に置き換え

❻その他
・文字の先頭を0埋めして桁数をそろえる。zfillを使い、()の中で桁数を指定する。

a=25
print(a) #==>25
print(str(a).zfill(6)) #==>000025

❼改行コードが入った長い文の改行コードを消す
・英文のPDFを日本語に翻訳しようとしたが、改行コードが入っている場合がある。改行コードをスペースに置き換えた上で、DeepL翻訳すると、きれいに翻訳してくれる。

data="""
ここに改行コードが入った英文など
"""
print(data.replace('\n',' '))

4.変数

・変数名は、最初に数字を使うことはできない。途中では数字を使える
・変数名には、-や+なども記号も使えない。使えるのはアンダーバー(_)
・大文字と小文字は区別される。つまり、変数としては別物

Moji='Hello'
print(Moji) #==>Hello
print(moji) #==>name 'moji' is not defined

・変数には、一般的な半角1バイト文字であるASCII文字だけでなく、2バイトとUnicode文字も使える、つまり、漢字やひらがななども使えるというわけである。以下がその実行結果。

文字='Hello'
print(文字) #==>Hello
(1)変数のデータ型

❶変数に値を入れる
>>>x = 100
>>>print(x)
100

>>>x, y, z = 100, 200, 300
>>>print(x,y,z)
100 200 300

>>>x=y=z =100
>>>print(x,y,z)
100 100 100

❷データ型の宣言は不要
cやJavaではデータ型を宣言していたが、pythonでは不要。便利ですよねー。
(文字を入れたら文字型に、数字を入れたら数値型にしてほしいって思ってた。)
たとえば、以下のように、直接値を入れればいい。
moji="こんちくは"

※ダブルクォーテーション”でもシングルクォーテーション’でもどちらでもいい

では、文字を変数で表示してみましょう。
moji="こんちくは"
print(moji)

(2)有効範囲

・変数は関数の中と外では、同じ変数aでも別物と扱われる。同時に定義することが可能。
・関数の内で宣言された変数はローカル変数、外で宣言されたのはグローバル変数
・有効範囲は、スコープとも呼ばれる。
・globalとつけることで、関数内に閉じない変数を宣言できる
 

(3)定数

 値を変えない定数を定義する場合は、大文字で書くことが慣習。(そういう処理ができるわけではない)
たとえば、消費税をTAX=1.08 とする

(4)データ型とキャスト

type()は、文字の型を表示する。
以下は文字を入れた場合と数字を入れた場合

>>> a="こんちくは"
 >>> type(a)

 >>> a=2
 >>> type(a)

 >>> a=12.345
 >>> type(a)

※Javaなどでは文字型(Char)と文字列(String)があったが、Stringで統一されている気がする

・型変換は、「キャストする」とも言う。
 変数の型を指示することで、型を変換できる。
int()  →int型に変換
str()  →文字型に変換
(例) 整数を文字と足すとエラーになるが、以下のようにstr(a)
として文字型にしている。

>>> a=3
 >>> "こんに"+a
 Traceback (most recent call last):
 File "", line 1, in 
 TypeError: can only concatenate str (not "int") to str
 >>> "こんに"+str(a)
 'こんに3'

5.数字と演算

(1)整数と実数(浮動小数点数)

数字には整数と、実数(浮動小数点数)の2つがある。実数は、小数点がある
❶実数を整数に変換 →int関数

print(int(1.5))  #==> 1

❷整数を実数に変換 →float関数

print(float(2))  #==> 2.0
(2)演算

Pythonに限らず、CやJavaでも基本的に同じである。
❶足し算  +
いくつかやってみましょう。

n=3
n+=5  # n=n+5と同じ 
print(n) # ==> 8
#文字列の足し算、掛け算もできる。引き算はできない。
print("こんち" + "くは")  #==> こんちくは
print("こんち" * 3)  #==> こんちこんちこんち

❷引き算  -
  n-=5 → n=n-5
❸掛け算  *
❹割り算  /
・割り算で、少数以下を切り捨てる  // 
 たとえば、10//3  →3になる
・あまり % 
 (例)5%2 →あまり1
【小数点の桁数と、INT型とFLOAT型】
ここで、整数の四則演算時に、小数点の桁数を確認する。

12/3 #==> 4.0 4ではなく、小数点第1位まで
12.0/3.0 #==> 4.0 
12.00/3.00 #==> 4.0 
5//3 #==>1 あまりに関しては整数
5.0//3.0 #==>1.0 小数点第1位まで
5.00//3.00 #==>1.0 小数点第1位まで
2*6 #==>12
2.0*6.0 #==>12.0
2.00*6.00 #==>12.0

整数の割り算で、結果が整数であっても、小数点第1位まで表示される。これは、結果の型による。型を表示してみるとわかる。たとえば、5はINT型で、5.0はFLOAT型である。よって、結果の型が変わり、小数点が表示されるのかが変わる。

print((5).__class__) #==<class 'int'>
print((5.0).__class__) #==<class 'float'>
print((5//3).__class__) #==<class 'int'>
print((5.0/3).__class__) #==<class 'float'>

まとめとして、整数の四則演算で結果が整数になる場合、小数点の表記がどうなるか。
結論は、割り算だけFLOATになって、小数点第1位まで表示される。

>>> 4+2
6
>>> 4*2
8
>>> 4/2
2.0
>>> 4-2
2
>>> 4//2
2
>>> 4%2
0

❺べき乗  
 2乗は **2 
 n乗は **n

【注意点】
・優先度は掛け算や割り算が優先 →優先順位を変えるには()を使う
・3+5*2であれば、掛け算が先
 (3+5)*2 とかっこをつけると、かっこの中が優先

❻大きい値を返す
>>> print(max(3,5,2))
5
❼ビット演算

1000<<3  #==>8000  3ビット左シフト、つまり8倍
1000>>3  #==>125  3ビット右シフト、つまり8分の1
(4)論理演算(ブール演算)

AND、OR、NOTのことと考えていい。ただ、通常のANDやORとは考え方が違うので注意が必要。
また、論理演算とビット演算の違いもあるので、andを使うのか、&を使うのかによって、出力結果が異なる点も注意が必要。
❶AND
・左がTrue(または空でない数字や文字)であれば右を返し、False(または0)であれば左を返す
・ANDではなく、&でも同じ結果になる。
・大文字のANDではなく、andと記載する。

1 and 2 #左が真なので、右の2を返す
0 and 2 #左が偽なので、左の0を返す
2 and 3 #左が真なので、右の3を返す 
True and False #左が真なので、右のFalseを返す

❷&
こちらもANDではあるがビット演算。つまり、01のビットにして計算する。andとする場合と結果が違うので注意

and 論理演算子
& ビット演算子
1 & 2 #==>0 01 10 をそれぞれ論理積を取るので、00
0 & 2 #==>0 00 10 をそれぞれ論理積を取るので、00
2 & 3 #==>2 10 11 をそれぞれ論理積を取るので、10 
True & False #==>False

❸OR
左がTrue(または空でない数字や文字)であれば左を返し、False(または0)であれば右を返す

1 or 2 #左が真なので、左の1を返す
0 or 2 #左が偽なので、右の2を返す
2 or 3 #左が真なので、左の2を返す 
True or False #左が真なので、左のTrueを返す

❹|

or 論理演算子
ビット演算子

以下のプログラムを書いてみた。

for i in range(2):
  for j in range(2):
    print(i,' | ',j,'=',i|j)

出力結果は以下である。

0  |  0 = 0
0  |  1 = 1
1  |  0 = 1
1  |  1 = 1

❺XOR
これで、xに、xと1のXOR演算結果を代入することができる。これで、ビット演算、つまり、0なら1、1なら0にできる。→まあ、NOTを使う方がすんなりいくかな。

x=1
x= x ^ 1
print(x) #==>0 また、x=0とすると、この結果は1になる

❻NOT
0と1を逆にする。ビット演算では「~」

a=0
a= not a
print(a) #==>True

ここで、日商Python検定の問題(公開されています)から、以下を試してみよう。

#①
10&0 #==>1010と0000のビット演算でANDを取るので、0000、つまり0
#②
10 >> 4 #==>0 1010を4ビット、右にズラすので、0
#③ 
~0 #==>-1 0のNOTなので1、だから-1?
#④ 
10^10 #==>1 1010 と1010 の排他的論理和 0000、つまり0
(3)不等号

❶等しい
・等しい  ==
1==1と実行すると、一致するのでTrueが返る。
ちなみに、1==1.00 もTrue

print('true')   #==>true
print(4/2 == 2)  #==>True ★=は2つ
a=2;print(a is 2)  #==>True
print(4/2 is 2) #==>False ★Trueじゃないよ
print(int(True)) #==>1 

※Trueは整数の1と、Falseは0とほぼ同様に扱われます。
❷等しくない
・等しくない  != 

a=2;print(a is not 3)  #==>True
print(4/2 != 2)     #==>False
a=2;print(a is not 2)  #==>False

❸大小
大きい >=
・文字列も大小を比較できる。比較方法は、Unicodeによる。大文字の方が小文字より小さい。

print(3>=0)  #True
#print(3=>0) # ==> NG SyntaxErrorになる

・タプルでも比較できる
('aa','ab') < ('abc','a') #==>True
これは、abcがaa、abのどちらよりも大きいからだと思う。

(4)存在するか、in と not in
print(11 in [10,11,12]) #==>True     
print(11 not in [10,11,12]) #==>False  

6.文字入力

javaに比べたら、驚くほど簡単である。なぜ、javaはあんなに面倒なんだろうか・・・

(例文)
print("文字を入力してください") 
a=input() #1行で、a=input("文字を入力してください")としてもOK
 print("あなたが入力した文字は" + a + "ですよねー。") 

入力された文字をint型にするには
a=int(input())

7.if文による条件分岐

・javaなどの場合、開始と終わりが{}で囲われていた。なので、どこまでがif文の内容なのかがわかりやすかった。
しかし、pythonでは{}がないので、改行位置で終わりを判断する。
・if文の最後にコロン(:)を忘れずに
・基本構文は以下

if 条件式:
 処理 #{}がないので、位置が重要。tabでインデントの調整をする
elif 条件式: #else if じゃないよ
 処理
else:
    処理

❶例として

a=70
if a>=80: # この条件が正しければ、以降の処理は行われない
  print("Good")
elif a>60:
  print("WoW")
else:
  print("Sorry")

❷複数条件の組み合わせ
条件を組み合わせることも可能。
and や or でつなげる。
a>60 and a<=70

❸サンプル
以下は、文字列mojiの中に、sがいくつ入っているかのプログラム

moji='I am a boy.I like sushi very much'
i=1
for a in moji:
  if a=='s':
    print(str(i) + '番目にsがあった!')
    i += 1

8.for によるループ

(1)ループの基本構造

python の場合CやJavaと比べて for のループの書き方が違う。単純になっているのだが、逆にわかりにくいと感じる人もいるだろう。
・Cなどの場合の構文

for(int i = 0; i < 5; i++)

・Pythonの場合

for i in range(5):
 print(i)

このように、カウンタを作って値を順番に変化させる場合には、rangeを使い、その下に処理内容を書く。
・for文の最後にコロン(:)を忘れずに
結果は以下。

0
1
2
3
4

・javaなどと同様に、break、continueも使える。以下は3と一致したらbreak(強制終了)している。

for i in range(5):
 if i == 3:
  break
 print(i)
(2)繰り返し処理を使う理由

シーケンスを使う大きな理由のひとつに繰り返し処理があります。同じ処理を異なる値に適用したい場合、シーケンスによって効率的に記述できます。
繰り返し処理にはfor文を用います。

for 変数 in シーケンス:
    繰り返す処理

このように記述すると、シーケンスの要素をひとつずつ変数に代入しながら処理が要素の数だけ何度も実行されます。
例えば、購入した商品の税抜き額が与えられたとき、その税込み額を表示するプログラムを作るとします。

prices = [100, 150, 600]
for price in prices:
    taxed = int(price*1.08)
    print(taxed)

以下のように、繰り返しが排除されてすっきりしました。

108
162
648
(3)文字列のループ

forによって繰り返しができるは、数字だけではない。文字列もできる。たとえば、以下はcにmsgの文字を先頭から順に1文字ずつ入れている。

msg = 'Hello'
for c in msg:
    print(c)

よって、結果は以下のようになる

H
e
l
l
o
(4)break

ある条件なども基に、ループを中断させます。

a=[10,20,150,30,120]
sum=0
for i in a:
    if i>=100: #100以上であれば、中断します。
        break
    sum += i
print(sum)
30
(5)continue

特定の条件の場合には、スキップします。

a=[10,20,150,30,120]
sum=0
for i in a:
    if i>=100: #100以上であれば、スキップします。
        continue
    sum += i
print(sum)
60
(6)ループの中にループを作らない

演算処理をするループAがあって、その中にループBを作ると、処理回数がA×Bと積になる。場合によっては、非常に非効率になる。
なので、ループの中にループができないような工夫が必要だろう。
❶forの中をforで回している

word=['a','b','c','a','a','a','b','d'] #文章にたくさんの単語が登場する
count_word=['a','b','c']  #単語の一覧
count={} #==>求めたいのは単語ごとの出現回数 {a:4,b:2,c:1}の、出現回数のみなので、[4,2,1]を返す
for i in count_word:
      count[i]=0 #辞書であるcountに,単語を入れる
      for j in word:
        if i == j:
          count[i] += 1
print(count) #==>{'a': 4, 'b': 2, 'c': 1}
print(list(count.values())) # ==> [4, 2, 1]

❷forを別々に実行

word=['a','b','c','a','a','a','b','d'] #文章にたくさんの単語が登場する
count_word=['a','b','c']  #単語の一覧
counter = {} 
for fw in word:
    counter[fw] = 0  # 初期化
for w in word:
    counter[w] += 1
# 順番は count_wordにあわせる
ans = []
for w in count_word:
#count_words にない ときは 0 に
    ans.append(counter[w] if w in counter else 0)
print(ans)

❸内包表記にしてみた。
もしかすると、1行でできるかもしれない。

word=['a','b','c','a','a','a','b','d'] #文章にたくさんの単語が登場する
count_word=['a','b','c']  #単語の一覧
counter = {x: word.count(x) for x in word}
ans=[j for i,j in counter.items() if i in count_word] #iがKEYで、jがValueである
print(ans)

9.イテレータ

・イテレータは、「次の要素」を持ってくるという処理ができる。これが、意外に便利だったりする。
・iterateは「繰り返す」という意味。for も裏ではイテレータとして動いています。リストや文字などのイテレータであれば、以下のように、値を先頭から順番に抜き出すことができる。
word=[1,2,3] #または、wor='abcdefg' などの文字が入っているとする。
for i in word
・イテレータが実際におもてに見えるかは別として(forは裏でイテレータが動いている)、イテレータで処理させるメリットがある。たとえば、大容量のデータファイルを読むとき、全部を読み込むとメモリを消費しますし、時間がかかったりします。そこで、イテレータで1行ずつファイルを開くというのも方法の一つである。
・イテレータは、next関数により、次の要素を取り出せる。
・iter()によってイテレータになれるものをイテラブルという。リスト、文字列、タプルなどが該当する。
・nextで次の値がない場合は、「StopIteration」を返す。
・余談であるが、iterable(反復可能)以外に、ミュータブル(mutable:変更可能)という言葉もある。たとえば、listはmutableだがタプルはイミュータブル(immutable)である。文字列(str)もイミュータブルである。なので、以下のように、strigの先頭を違う文字に書き換えようとしても、エラーになる。

word = 'Hello'
word[0] = 'Z' #TypeError: 'str' object does not support item assignment

以下に整理されている。
https://gammasoft.jp/blog/python-built-in-types/

(1)簡単な例

❶リストをイテレータに変換

a=[10,20,30]
print(iter(a))
it_a=iter(a)    #リストをイテレータに変換
print(next(it_a)) #次の値を呼ぶ
print(next(it_a))
<list_iterator object at 0x7f382d6c8730>
10
20

❷ファイルでやってみる

with open('file.txt', 'r') as f:
    for line in f:
        print(line)

・以下のように、nextでイテレータの処理をさせてみる。

#!/usr/bin/python3.7
# -*- coding: utf-8 -*-
with open('/root/python/file1.txt','r') as file1:
    print(file1)     # -> <_io.TextIOWrapper name='/root/python/file1.txt' ・・・>
    print(next(file1))   # => 1:aaa ※ファイルの1行目が表示される。
    print(next(file1))   # => 2:abc ※ファイルの2行目が表示される。

(2)クラスでのイテレータ
ちょっとよく分かっていないが、恐らく、forなどによるイテレータ処理の場合、以下のようになっていると思われる。

class Iter1:
    def __init__(self):
        ・・・・
    def __iter__(self):
        ・・・・
    def __next__(self):  
        ・・・・

x = Iter1(10, 20, 30)

これは、Iter1というクラスにおいて、イテレータの処理が求められた場合に、 __iter__() メソッドを呼ぶ。そこで、イテレータをセットし(?)、nextで次に渡す?? かなり怪しいが、雰囲気はそんな感じだともう。
❷関数の場合
自分の理解のためにやっているが、正直、あまりわかっていない。
・リストを関数にしてイテレータを返してみる。これをみると、リストの項目を順番に返しているようにみえる。

def func1(x):
  a=iter(x)
  return a
  
list1 = func1([0,2,4,6,8])
print(list1)   # => <list_iterator object at 0x7f96d008e7f0>
print(list(list1)) # => [0, 2, 4, 6, 8]

・次はnextを1回実行して返してみる。リストの項目を順番に受け取って、nextして返しているようにみえる。

def func2(x):
  a=iter(x)
  next(a)
  return a
  
list2 = func2([0,2,4,6,8])
print(list2)  # => <list_iterator object at 0x7f96d00e9be0>
print(list(list2))   # =>  [2, 4, 6, 8]

❸クラスの場合
以下の例を見てみる。userというリストに、extendでuser1,user2,user3という値を順にセットする。

user=[]
user.extend(['user1','user2','user3'])
print(user)
for i in user:
    print(i)   

すると、以下のようにuserのリストに値がセットされ、 forでイテレータを回すと user1 user2 user3 が順に表示される。

['user1', 'user2', 'user3']
user1
user2
user3

・では次に、Classでやってみる。

class User:                  #Userクラスを定義
    def __init__(self):
        self.list_user = []   #list_userという空のリストを作る
    
user = User()        #userというインスタンスを作成
user.list_user.extend(['user1','user2','user3'])     # userというインスタンスのuser.list_userというリストに、値を入れる
print(user.list_user)    # => ['user1', 'user2', 'user3']     ※user.list_userというリストを表示すると、リストが作成されていることがわかる。
for i in user.list_user:     #さきと同じように、イテレータのforで回す。
    print(i)

やっていることは同じなので、さきと同じ結果になる。
では、最後の下から2行目を以下のようにしてはどうなるか。

for i in user:

もちろん、userだけでは分からないので、「'User' object is not iterable」として怒られる。
❸クラスではイテレータの処理を明示的に入れる必要がある?
先ほどのプログラムに、イテレータの処理を入れる

class User:
    def __init__(self):
        self.list_user = []
    def __iter__(self):  #イテレータの処理
        return iter(self.list_user)

user = User()
user.list_user.extend(['user1','user2','user3'])
for i in user:
    print(i)

すると今度は、エラーがでずに、user1からuser3が表示された。
これは、Classにおいて、イテレータとして処理してほしい場合に、自動でdef __iter__(self): の関数を実行してくれる。
なんとなく、以下のように変更しても動くような気がするが、non-iterator of type と怒られるので、イテレータ型にすべきなんだろう。

    def __iter__(self):  #イテレータの処理
        return self.list_user
(3)イテレータとリストのキャスト

リストはイテレータである(と思う)。Pythonでは、イテレータとして動いて欲しい場合に、自動でイテレータに変換してくれることが多い。なので、イテレータなのか、イテレータとして動くものなのかが少しごっちゃになると思う。
たとえば、以下の2つは同じ結果になる。どちらも、10 20 30が改行されて順に表示される。

a=[10,20,30]  # リストを定義
for i in a:
    print(i)

・リストをイテレータに変換

a=[10,20,30]  # リストを定義
for i in iter(a):
    print(i)

もう少し確認のため、ここでは、明示的にキャストしてみたいと思う。リスト→イテレータ→リストとする。

a=[10,20,30]  # リストを定義
it_a=iter(a)  # リストをイテレータにcast
print(it_a)   # => <list_iterator object at 0x7f00961f0730>
b=list(it_a)  # イテレータをリストにcast
print(b)      # => [10, 20, 30]
(4)イテレータとmap

・関数とイテレータ(厳密には違うがリストと考えるといい)を受け取り、リストに関数を適用する。
・イテレータを都合がいいものに編集するものがmapと覚えればいいのではないか。
・出力はリストではなく、mapオブジェクトという一種のイテレータ。
・イテレータなので、list()によってキャストすればリストになるし、for文であればそのまま使える。
・構文としては以下になる。
map(関数、イテレータ)
❶リストを2倍にするmapを作ってみる。

def doble(n):
    return n*2
a=[1,2,3]
b=map(doble,[1,2,3])  
print(b)  # => <map object at 0x7f4d9d4ee7f0> ※map objectとあるように、mapオブジェクト。リストではない。
print(list(b)) # => [2, 4, 6] 

※本来は、mapの規則だと、4行目は以下であるべき。ただ、イテレータにしなくても、イテレータになってくれている。
b=map(doble,iter([1,2,3]))

・イテレータであるので、そのあたりの理解をするためにも以下を実行

def doble(n):
    return n*2
a=[1,2,3]
b=map(doble,[1,2,3])  
print(iter(b)) # => <map object at 0x7f2e3fa457f0>
print(next(iter(b))) # => 2
print(next(iter(b))) # => 4
print(list(b)) # => [6] 

・イテレータの理解のために、以下も実行。イテレータなので、for文でそのまま使える。

def doble(n):
    return n*2
a=[1,2,3]
b=map(doble,[1,2,3])  
for c in b:
    print(c) # => 順に2 4 6 が表記される。
(5)ジェネレータ(generator)

・ジェネレータは、イテレータを作る関数のことである。なので、普通にdefで関数を定義する。
イテレータのメリットにあったように、1つずつ処理をするので、一度に大量のメモリを必要とせず、処理が高速になることがある。→使い方次第で、大きな利点に。
・yield文を使うことが多い。yieldはReturnの代わりに使う。
以下、サンプルである。func1という関数をジェネレータ(つまり今回はイテレータの機能を持つ)にしている。yieldは1つずつ結果を返す。

def func1(n):
    while True:
        yield n
        n += 1

a=func1(5)
print(a) # => <generator object func1 ~ ※ここにあるように、ジェネレータである。
print(next(a)) # => 5
print(next(a)) # => 6  ※nextによって、次の値を取得する。
print(next(func1(5))) # = > 5 初期化されるのでこのようにやると、何度nextを実行しても5のままである。
(6)イテレータとfilter

・mapに似たものに、filterがある。これも以下の構文である。
  filter(関数、イテレータ)
・こちらもmapと同様に、イテレータを加工して、都合がいいmapを作る。
・関数で指定した条件で、Trueになる値だけを抜き出す
・返り値はイテレータなのでリストではない。が、リストにキャストしたり、for文で利用できる。
・以下は、range(10)から偶数だけを抜き出すfilterであるfunc1を作った。

def func1(n):
    return n % 2 == 0 #偶数ならTrue

a=filter(func1, range(10)) 
print(a)         # => <filter object at 0x7fd7c67fd430>
print(list(a))  # => listにcast [0, 2, 4, 6, 8]

※構文からすると、3行目は a=filter(func1, iter(range(10))) としてrangeをイテレータにすべきかな。

9.while によるループ

他のプログラムと同様、for 以外にwhileでループもできる。
こちらも、elseやbreak、continuなども使える

❶簡単な例でやってみる
先ほどのforをつかって、0 1 2 3 4 を表示する。

for i in range(5):
    print(i)

whileを使うと、こんな感じ。

i=0
while i<5:
    print(i)
    i += 1

forに比べて、どうしても文が長くなってします。
❷無限ループ
以下のように、while で条件をTrueにすると、無限ループが設定できる。以下は、入力を求め、その入力値を表示する。これが無限に行われる。

while True:
    x = input("please input")
    print("your input=" + x)

10.内包表記

(1)概要

やっていることはforと同じだが、行数を少なく書くことができる。
構文としては、配列の場合は以下
[処理結果 for 値 in 配列等]

ためしにやってみよう。
(例)2乗の値をリストに入れる
❶forを使う

x=[]
for i in range(4):
    x.append(i**2)
print(x) #→[0, 1, 4, 9]

❷内包表記を使う。もちろん結果は同じだが、とてもシンプルに書くことができる。

x= [i**2 for i in range(4)]
print(x) #→[0, 1, 4, 9]
(2)いくつかの例

❶配列の処理も可能

word=['a','b','c']
data = list(x*2 for x in word)
print(data) #==>  ['aa', 'bb', 'cc']

❷辞書も作成可能(以下はValueを0に初期化)

word=['a','b','c']
data = {x: 0 for x in word}
print(data) #==> {'a': 0, 'b': 0, 'c': 0}

❸出現回数を計算した辞書も作成可能

word=['a','b','c','a','a','a','b','d'] 
data = {x: word.count(x) for x in word}
print(data) #==> {'a': 4, 'b': 2, 'c': 1, 'd': 1}
(3)高度な事例

❶if文で条件を指定する。
今回は、奇数だけを抜き出す。(2で割った余りが1という真理値がTrueの場合)

x = [i for i in range(10) if i % 2 == 1]
print(x) # ==> [1, 3, 5, 7, 9]

❷内包表記を繰り返す

#まずは、分かりやすい例
x = [[i,0] for i in range(3) ]
print(x) #==> [[0, 0], [1, 0], [2, 0]]
#iとjの両方で内包表記を2回
x = [[i+j for i in range(2)] for j in range(3)]
print(x) # ==> [[0, 1], [1, 2], [2, 3]]

11.リスト (=CやJavaなどでいう配列)

CやJavaで初めて学習したときは、ピンときませんでしたが、便利です。
添え字というか、番号は0から始まる
まず、全体像としてPythonの コレクションとして、以下の4つがある。
                   

名称 ミュータブル イテラブル 備考
集合 set {1, 2, 3, 5, 6} - 重複無し 
タプル tuple ('word',123) × ただし、x = (1, 2); x = x + (3, 4)  はできる
リスト(配列) list ['word',123] -
辞書 dict {'ito':23, 'suzuki':21, 'kato':16} - -
(1)基本操作

❶初期化

a=[] #リストを初期化しているイメージ

❷配列を定義

a=[75,70,80,90,70] #5教科の点数をイメージ

配列には、数字や文字などの型が違うものを入れてもいい。

ab=[75,70,'abc','d',70]
print(ab) #[75, 70, 'abc', 'd', 70]

※注意点として、文字列は''で囲う
・以下のようにforなどを入れてもいい。

ab=[x**2 for x in range(5)]
print(ab) #[0, 1, 4, 9, 16]

❸配列の表示

a=[75,70,80,90,70] #5教科の点数をイメージ
print(a) # [75,70,80,90,70] と表示

❹指定された項番を表示

print(a[0]) #先頭の項目である75を表示
print(a[3]) #4番目の項目である90を表示
print(a[-1]) #最後の項目である70を表示
print(a[1:3]) #範囲を指定して表示 この場合1~2まで。終了部分は-1して表示 →[70, 80]
print(a[:2]) #==>[75, 70]
print(a[:4]) #==>[75, 70, 80, 90]
print(a[:]) #==>[75, 70, 80, 90, 70]
print(a[:0]) #==>[]
print(a[:-1]) #==>[75, 70, 80, 90] 、最後から1項目を削除
print(a[:-3]) #==>[75, 70]、最後から3項目を削除

❺値の変更 

ab[2]=100 #3番目を100に変更する
print(ab) #[75, 70, 100, 90, 70]

❻リストの長さ(項数)

a='123456'
print(len(a)) #==> 6
d = 'abc\nde\t'
print(d) #==> abc de
print(len(d)) #==>7 改行コードも1文字としてカウント

❼合計や平均を算出 ※便利だ

print(sum(a)) #合計385を表示
print(sum(a)/len(a)) #平均点77を表示

❽enumerate関数
enumerateは「一覧化する」という意味。以下のように、リストの中身を、通番とともに表示してくれる。

a=['tokyo','osaka','nagoya'] 
print(a) #==>['tokyo', 'osaka', 'nagoya']
for i in a:
    print(i)
for i,j in enumerate(a):
    print(i,j)

出力結果は以下

['tokyo', 'osaka', 'nagoya']
tokyo
osaka
nagoya
0 tokyo
1 osaka
2 nagoya
(2)リストの操作

リスト(配列)のソート(小さい順に並べる)したり、逆にしたりできる

ab=[75,70,80,90,70]

❶ソート

ab.sort() 
print(ab) //→結果 [70, 70, 75, 80, 90]

ここで、リストはミュータブルなので、元データを書き換えてしまう。
リストとタプルの違いがわかるように、一部が繰り返しになるが、もう一度実行する。

a=[75,70,80,90,70]
a.sort() #ミュータブルなので、変更可能。よって、aが変更(上書き)されて、[70, 70, 75, 80, 90]
b=tuple(a) #型をタプルに変換
print(b) #==>(70, 70, 75, 80, 90)
b.sort() #==>'tuple' object has no attribute 'sort' タプルはイミュータブルなので、値を変更してしまうsort関数を持たない

❷逆にソート

ab.reverse() // 逆にする
print(ab) //→結果[90, 80, 75, 70, 70]

❸リストの追加
・insert
以下は、先頭に100を追加する。0は位置で、先頭。-をつけると、後ろから何番目という書き方もできる。-2であれば後ろから3番目

ab.insert(0, 100) 
print(ab) # => [100, 75, 70, 80, 90, 70]

・末尾に追加 append

ab=[]
ab.append(10)
ab.append(5)
print(ab) #→結果は[10, 5]

・または、以下のように足し算で書いてもいい。これは、set(セット)ではできないと思う。もちろん、タプルはイミュータブルなので、あとから変更は不可。

ab=[]
ab.append(10)
ab = ab + [5]
print(ab) #→結果は[10, 5]

❹削除 remove
・最初も要素だけ削除する。

ab=[75,70,80,90,70]
ab.remove(70) #==>[75, 80, 90, 70]

・全部削除するには、少し工夫が必要。たとえば、内包表記を使うなら以下。

ab2 = [a for a in ab if a != 70]

・数を数えてループで回すなら以下。

for i in range(ab.count(70)):
    ab.remove(70)

・リストを空にする

a.clear() # ==> []リストを空にする。結果は[]

・部分的に削除

del a[:] # ==> [] clearと同じ結果になる。すべて削除
del a[:3] # ==> [90, 70]リストの前から3項目を削除 

❺リストから検索

#単にあるかどうか
print(80 in ab) //→結果True
#いくつあるかをカウント
print(ab.count(70)) #==> 2

❻リストのスライス
リストの中で、指定された範囲の文字を抜き出す。

print(ab[2:4])  # => [80,90]
print(ab[:4])  # => [75, 70, 80, 90]

1つ目であるが、少し紛らわしいが、配列のab(2)からab(3)までを表示する。なので、今回でいうと、3番目から4番目ということで、[80,90]
❼リストのアンパック
アスタリスク(*)を使うと、リストを要素に分解できる

x = [1, 3, 5]
print(*x) #==>1 3 5
(3)配列の処理

❶基本的な処理
・clear 配列の全ての要素を削除
・remove 該当する要素の最初を削除
・del  インデックスを指定するなど
・appendで末尾(end)に追加(app)
・extendでリストを結合できる
いくつかやってみる。

x=[75,70,80,90,70]
x.append(95) #==> [75, 70, 80, 90, 70, 95]
x.pop() #==> [75, 70, 80, 90, 70]
x.remove(70) #==>[75, 80, 90, 70]
x.clear() #==>[]

❷pop()
配列から値を取り出すことができる。また、取り出した値を表示する。通常は配列の一番後ろから。値を入れることで、取り出す要素を指定できる。以下は、0を指定して先頭の要素を取り出した。また、それをprintすると、取り出した要素を出力する。

x=[1, 2, 3, 4]
print(x.pop(0)) #==>1
print(x) #==>[2, 3, 4]

❸deque
listはpop処理ができたので、スタック構造として扱うことができた。しかし、キュー(つまりFIFO)としては使えない。使うためにはdequeがいいだろう。
appendleftやpopleftが使える

from collections import deque
x=[75,70,80,90,70]
x2=deque(x)
x2.appendleft(95) #==> deque([95, 75, 70, 80, 90, 70])
x2.popleft() #==> deque([75, 70, 80, 90, 70])
print(x2)
(4)リストの最大値とそのインデックス

以下を実行しながら、リストの最大値やインデックスの求め方を確認しよう

a=[1,2,3,9,8]  
print(max(a)) #リストの中の最大値を返す→9
print(a.index(max(a))) #aの最大値のインデックス(つまり何番目か)を表す。→3
b=[[1,2,3],[9,8,7,6],[4,5]]  
print(max(b)) #最大値を持つリストを返す。→[9, 8, 7, 6]
print(max(max(b))) #最大値を持つリストの中の最大値を返す。→9
print(b.index(max(b))) #bの最大値が何行目か →1(2行目)
print(max(b).index(max(max(b)))) #bの最大値が何列目か →0(1番目)

ただ、なぜかリストに0が入ると、上記では最大値の計算がうまくいかなかった。そこで内包表記を使って最大値を求めたのが以下

b=[[1,2,3],[0,9,8,7,6],[4,5]]  
print(max(max(b))) #最大値を持つリストの中の最大値を返す。→なぜか5
max_number = [max(i) for i in b] #内包表記で書くリストの最大値を求める→max_numberには[3,9,5]が入る
print(max([max(i) for i in b])) #上記の最大値を返す →9
(5)リスト[ ]とタプル( )

❶概要
[ ]はリスト(配列)です。それ以外に、タプル( )があります。ちなみに、辞書{ }もあります。タプルは変更できないリストのようなものです。どちらも似たようなものですが、タプルは新規で作るしかなく、後で値を変更できません。ただ、単純な処理だけであればタプルの方が高速です。また、途中で変えてほしくない値を扱う場合にも便利。
❷実際にやってみる

x = ('word',123)    #タプル。 複数の型を混在が可能。
print(x)       #==>('word', 123)
y=['word',123]  #リスト。複数の型を混在が可能。
print(y)       #==> ['word', 123]
z='word',123  #タプル カッコを省略してもタプルになる。
print(z)       #==>('word', 123)

・また空のタプルと要素が1つだけのタプルも作ろう。1つの要素のタプルは、後ろにカンマが必要なので注意

x=() #==>空のタプルを作成
print(x) #==>()
y=(1) #==> タプルにならない
print(y) #==>1
print(type(y)) #==><class 'int'> このように、単なる数字になる。
z=(1,) #==> このように後ろにカンマ(,)が必要
print(z) #==>(1,)
print(type(z)) #==><class 'tuple'>
#項目を一つ加える場合は、以下のようにする
z=z+(3,)
print(z) #==>(1, 3)

❸リストとタプルの変換
両者の変換は簡単で、タプルにするにはtuple、リストにするにはlistで囲います。

x = ('word',123)#タプル 
y=['word',123]#リスト
new_x=list(x)
print(new_x) # => ['word', 123]
new_y=tuple(y)
print(new_y) # => ('word', 123)

❹変数にカンマで数字と文字を入れてみる
これは参考程度に考えればいい。以下のように、a = 12,'ab' とすると、タプルになる。

a = 12,'ab'
print(a)  #==>(12, 'ab') タプルになる
print(type(a)) #==> <class 'tuple'>
b = [12,'ab'] #これは参考
print(b) #==> [12, 'ab']
print(type(b)) #==> <class 'list'>

❺zip関数・・・行でまとめるなど
list(zip(*x))  →タプルになる
list(map(list, (zip(*x))))  →リストになる

a=[1,'aoki',35]
b=[2,'sato',20]
c=[3,'goto',24]
x=[a,b,c]
print(x) #==> [[1, 'aoki', 35], [2, 'sato', 20], [3, 'goto', 24]]
y=list(zip(*x)) #==> 列でまとめる
print(y) #==> [(1, 2, 3), ('aoki', 'sato', 'goto'), (35, 20, 24)]
print(y[1]) #==>('aoki', 'sato', 'goto')
print(list(y[1])) #==>リストに変換する場合 ['aoki', 'sato', 'goto']
z=list(map(list, (zip(*x)))) #いきなりリストにもできる
print(z) #==>[[1, 2, 3], ['aoki', 'sato', 'goto'], [35, 20, 24]]

こんな使い方もできる。以下は、各リストを先頭から順に表示する

a=[1,'aoki',35]
b=[2,'sato',20]
for i,j in zip(a,b):
    print(i,j)
(6)set(セット、{})

・リストとタプル以外に、セットというものがある。復習も兼ねるが、リストは[]、タプルは()、辞書は{}、セットも{}である。
・特徴は、①重複がない、②順序性が無い。
①の重複が無いというのは便利な機能である。重複を自動で排除してくれるからだ。
・setは型であるが、関数としても使える。重複しない要素として出力することができる。
❶基本的な操作、以下、実行例。

a=[1,1,2,2,2,3,5,6,3]
b=set(a)
print(b)  # => {1, 2, 3, 5, 6}
print(set('asbdkabdk')) # => {'s', 'k', 'd', 'a', 'b'}
print(len(b)) # => セットの長さである5を返す
print(5 in b) # セットに値があるかを確認 => True
b.add(4) # 4を追加する
b.remove(1) #1を削除する
print(b) # => {2, 3, 4, 5, 6}

❷集合演算
以下のように、集合演算ができる。

set1={1,2,3}
set2={3,4}
print(set1 | set2)  # 和集合 =>{1, 2, 3, 4}
print(set1 & set2)  # 積集合 =>{3}
print(set1 - set2)  # 差集合 =>{1, 2}
(7)リストにデータを入れる

・カンマ区切りの文字を、カンマ単位でリストに入れる。

moji='abc,cde,fgh,ijk'
x=moji.split(',') #カンマ単位で配列に入れる
print(x)  #==>['abc', 'cde', 'fgh', 'ijk']

12.多重リスト(2次元配列)

(1)概要

DBというのか行列というのか、縦横の表になっているリストを扱えます。つまり、DBの操作ができるようなイメージです。
縦と横の項目の数はずれていても問題ない。たとえば、[1,2,3],[75,70]と入れてもいい。
❶多重リストに値をセット
ab=[[1,2,3],[75,70,80],['x','y','z']]
❷表示
print(ab) #[[1, 2, 3], [75, 70, 80], ['x', 'y', 'z']]
print(ab[1]) # 2番目のみを表示 →[75, 70, 80]
print(ab[1][0]) #2番目の最初の値を表示 →75
❸リストにリストを入れることも可
cd=[ab,[4,5],['a','b','c']]
print(cd) #[[[1, 2, 3], [75, 70, 80], ['x', 'y', 'z']], [4, 5], ['a', 'b', 'c']]

(2)初期化

2次元配列の考え方は少し複雑だ。順番に確認していこう。行は、縦方向にいくつあるか。列は横の項目がいくつあるか。
たとえば、ab=[[1,2,3],[75,70,80]] であれば、2行3列の行列。
❶順番に初期化してみよう。

T=[]        #行と列を指定しない。ただ、これだとあまり意味がない。たとえば、1行1列目に1という値を入れようとして T[0][0]=1 としてもエラーになる。
print(T)
T1=[[0], [0]]
print(T1)
T2=[[0,0], [0,0]]
print(T2)

結果は

[]
[[0], [0]]
[[0, 0], [0, 0]]

❷掛け算を使って0を入れる

T=[0]*2                    #1×1の行列が1×2になる。
print(T)
T1=[[0], [0]]*2           #1×2の行列が4×1になる。
print(T1)
T2=[[0,0], [0,0]]*2    #2×2の行列が4×2になる。
print(T2)
T3=[[0]*3]*2    #1×1の行列が1×3になり、1×3の行列が2×3の行列になる。
print(T3)

結果は

[0, 0]
[[0], [0], [0], [0]]
[[0, 0], [0, 0], [0, 0], [0, 0]]
[[0, 0, 0], [0, 0, 0]]

❸推奨の方法
ただし、上記のような初期化はあまり推奨されていない。以下をやってみると分かる。T2の1行1列目の値を9に変更したとする。すると、他の値も変わってしまう。

T2=[[0,0], [0,0]]*2
print(T2)
T2[0][0] = 9
print(T2)

結果は

[[0, 0], [0, 0], [0, 0], [0, 0]]
[[9, 0], [0, 0], [9, 0], [0, 0]]

推奨の方法は、以下である。

T = [[0 for i in range(3)] for j in range(2)]
print(T)
[[0, 0, 0], [0, 0, 0]]

❹こんなやり方もあるだろう。
・まっさらなリストの末尾に0を追加していく。

R = []
print(R)
for i in range(3): 
    R.append(0)
print(R)

結果は以下

[]
[0, 0, 0]

これを行と列でループを回す

T = []
for j in range(2):
    R = []  #毎回初期化する
    for i in range(3): 
        R.append(0)
    T.append(R)   #行ごと追加する。
print(T)
[[0, 0, 0], [0, 0, 0]]
(3)転置行列

行列Mが与えられたとして、その行と列を入れ替えるた行列Tを返すプログラム。len(M) で行の数、len(M[0]) は列の数を得る。
・空のリストを作って、そこに入れていく

def func_trans(M):
##まずは空のリストを作る
    T = []
    for j in range(len(M[0])):
      R = []
      for i in range(len(M)):
        R.append(0)
      T.append(R)
##空のリストに値を入れる
    for i in range(len(M[0])):
      for j in range(len(M)):
        T[i][j]=M[j][i]
    return T

・(こっちが教科書的) 空のリストを作りながら値を入れていく

def func_trans(M):
  T = []
  for j in range(len(M[0])):
      R = []
      for i in range(len(M)):
        R.append(M[i][j])
      T.append(R)
  return T

12.range関数

・ある範囲の数を定義できる。たとえば、range(5)であれば、0~4までの値が入っている。
・range関数の構文は、以下である

range(start, stop, step])

startから始まり、stopの一つ前まで、setpの公差
❶中身を表示

print(range(5))  # ==>  range(0, 5)   0~4の数字が入っているという意味

❷range関数で配列を作る

ab=list(range(5))
print(ab)  # ==> [0, 1, 2, 3, 4]

❸0以外でスタートする。startが3でstopが9

print(list(range(3,9)))  # == > [3, 4, 5, 6, 7, 8]

❹公差が3
以下は、1から始まり、9でStop、公差が3

print(list(range(1,9,3)))  # == > [1, 4, 7]

❺for文で使う

for i in range(5):
    print(i)

これにより、0から4が表示される。
単に、0から4のループとしても使える。

13.辞書

(1)辞書について

key(キー)とValue(値)からなる。2つで1セットと考えるといい。
(例)
キー:値
apple:3
orange:5
lemon:7
・辞書は英語のスペルのような役割を持ちます。たとえば、red:赤 のように。
・このように、辞書形式というか表形式の値を持てます。
・辞書型は{}で囲います。
・キーに入れることができるのは、イミュータブル(変更不能)なものだけ。なので、数字や文字、タプルは可能。しかし、リストは不可能。以下のように混在も可能。

x={1:'red','No.2':'blue',(1,2,3):'yellow'}
print(x) #==>{1: 'red', 'No.2': 'blue', (1, 2, 3): 'yellow'}
(2)基本操作

❶辞書の作成

#初期化
fruit={}
#作成
fruit={'apple':3,'orange':5,'lemon':7}

❷表示
・値の表示

print(fruit['apple'])  # =>3

※このように、Keyから値を出すことはできるが、逆はできない。print(fruit[3])とすると、エラーになる。
※このあとに書くgetメソッドがお勧め。エラー処理などができるため。

fruit={'apple':3,'orange':5,'lemon':7}
#辞書全体の表示
print(fruit)  # => {'apple': 3, 'orange': 5, 'lemon': 7}
#タイプ(型)を見てみると、dict(辞書)になっている
print(type(fruit)) # =><class 'dict'>

・辞書そのもの(リストに変更)

print(list(fruit.items()))  # => [('apple', 3), ('orange', 5), ('lemon', 7)]

・Keyだけ(リストに変更)

print(list(fruit.keys()))  # => ['apple', 'orange', 'lemon']
print(fruit.keys())  #dict_keys(['apple', 'orange', 'lemon'])

・値(Value)だけ(リストに変更)

print(list(fruit.values()))  # =>[3, 5, 7]
print(fruit.values())  #dict_values([3, 5, 7])
(2)各種の操作

❶データの追加、値の変更
実は、データの新規追加とデータの値の変更は、書き方は同じ。以下のように、キーで指定した値がなければ追加し、値があれば、上書き(変更)する。

# 追加
fruit['banana']=9

# 値の変更
fruit['apple']=4

こんな書き方もできる。

fruit['apple'] += 1 
print(fruit['apple']) #==> 4

❷値の検索
辞書にキーが存在するかどうか
print('banana' in fruit)
→結果はTrueまたはFalse

❸値の合計
・sumを使うと合計してくれる。

print(sum(fruit.values())) ==>15

・参考であるが、forで一つずつ回すと以下

goukei=0
for i in fruit.values():
  goukei +=i
print(goukei)  #==>15

❹その他
他と同様に、長さlenや削除delなど
❺リストを辞書に変換
dict()関数を使う

x=[('apple',3),('orange',5),('lemon',7)]
x2=dict(x)
print(x2) #==>{'apple': 3, 'orange': 5, 'lemon': 7}

❻2つの辞書の足し算
「+」ではできなかった。updateを使う。

x={'apple': 3, 'orange': 5}
y={'lemon': 7}
x.update(y)
print(x) #==>{'apple': 3, 'orange': 5, 'lemon': 7}
(3)メソッド

❶表示 get
既に述べたように、getメソッドを使わなくても値を表示できる。だが、エラー処理やいろいろなことができるので、こちらが便利
print(fruit['apple'])
→3
print(fruit.get('apple'))
→3
print(fruit['banana'])
→存在しないので、エラーになる。これでプログラムが止まってしまう。
print(fruit.get('banana'))
→None

❷KEYがあるかによって表示したり追加したりする setdefault
setdefaultは便利なメソッドで、KEYがあれば値を表示し、なければ追加する。
print(fruit.setdefault('apple', 9))
→3
print(fruit)
→{'apple': 3, 'orange': 5, 'lemon': 7}
print(fruit.setdefault('banana', 9)) #これは、単に表示しているだけなく、辞書に登録もしている。
→9
print(fruit)  
→{'apple': 3, 'orange': 5, 'lemon': 7, 'banana': 9}

❸削除 
指定したKEYを削除する場合はpop、全て消す場合はclear
fruit={'apple':3,'orange':5,'lemon':7}
fruit.pop('apple')
print(fruit)
→{'orange': 5, 'lemon': 7}
fruit.clear()
print(fruit)
→{}

(4)forで回す

❶辞書をそのまま指定すると、KEYが表示される
ここは、KEYとValueの両方が表示されると思ったが、違った。

fruit={'apple':3,'orange':5,'lemon':7}
for i in fruit:
  print(i)  #==>順にapple orange lemon

❷辞書全体で回す

for i in fruit.items():
  print(i)  #==>順に('apple', 3) ('orange', 5) ('lemon', 7) 

❸Valueで回す

for i in fruit.values():
  print(i)  #==>順に3  5  7

❹KEYで回す

for i in fruit.keys():
  print(i)  #==>順にapple orange lemon

❺両方で回す

for i, j in fruit.items():
    print(i, j)  #==>順にapple 3  orange 5 lemon 7

❻上と同じことを、リストにしてしまえば、こんな感じ

fruit2=list(fruit.items())
for i,j in fruit2:
  print(i,j)  #==>順にapple 3 orange 5 lemon 7

・別のやり方

fruit={'apple':3,'orange':5,'lemon':7}
for x,y in fruit.items():
    print("{0} is {1}".format(x,y))

結果は以下のようになる。{0}に始めの引数であるkey(今回は変数x)、{1}に次の引数であるvalue(今回は変数y)が入る。

apple is 3
orange is 5
lemon is 7
(5)並び替え

KEYとVALUEでもやり方が違うので注意
※すべてリストになっているので注意!!
❶辞書を定義

fruit={'apple':3,'orange':5,'lemon':7}

❷KEYでのソート

fruit2 = sorted(fruit.items())
print('fruit2=',fruit2)  #==> [('apple', 3), ('lemon', 7), ('orange', 5)]

❸KEYでのソート(降順)

fruit3 = sorted(fruit.items(), reverse=True)
print('fruit3=',fruit3)  #==> [('orange', 5), ('lemon', 7), ('apple', 3)]

❹VALUEでのソート ==>少し工夫がいる。lambdaを使う

fruit4 = sorted(fruit.items(), key=lambda x:x[1],reverse=True)
print('fruit4=',fruit4) #==> [('lemon', 7), ('orange', 5), ('apple', 3)]

❺[参考]上記のやり方で、KEYでのソート

fruit5 = sorted(fruit.items(), key=lambda x:x[0],reverse=True)
print('fruit5=',fruit5) #==> [('lemon', 7), ('orange', 5), ('apple', 3)]

13.モジュール

(1)モジュールについて

関数よりも大きな次元で、ファイルとして部品化すること。
たとえば、印刷機能などは、どのプログラムでも使うので、モジュールとしてどのプログラムからでも呼び込めるようにしたほうがいい。
また、モジュール、オブジェクト、メソッドについて理解しておこう。

名前 解説 datetimeモジュールの場合
モジュール プログラムのまとまり? datetime
オブジェクト モジュールに含まれる関数? date , datetime
メソッド オブジェクトが持つ関数? today() ,now()

具体例でみていこう。
・以下では、datetimeモジュールをインポートしている。
・datetimeには日付と時刻の情報を持つdatetimeと、日付の情報を持つdateがあり、どちらも利用できる。
・またdatetimeというモジュールの表記を省略してもいい。

import datetime
print(datetime.date.today())  # => 2021-01-03 
print(datetime.datetime.today())  # => 2021-01-03 02:54:52.192751
print(date.today())           # => 2021-01-03

次は、インポートする際に、オブジェクトを指定する方法

from datetime import date
print(date.today())           # => 2021-01-03
print(datetime.date.today())  # => 2021-01-03 

この場合、datetimeのオブジェクトはインポートしていない。だから、datetimeオブジェクトを使おうとすると、「NameError: name 'datetime' is not defined」というエラーが出る。

from datetime import date
print(datetime.datetime.today())  # ==> NameError: name 'datetime' is not defined
(2)外部モジュールの利用

❶使い方
pythonでは外部モジュールを読み込むことで利用できる関数を拡張することができます。
モジュールを使うにはimportする。標準モジュールの場合は、すでに組み込まれているので、宣言するだけ。
標準ライブラリ以外のモジュールは別途pipコマンドなどでインストールが必要です。Linuxのyumみたいなものかな。

import モジュール名

これによって外部モジュールに含まれる関数が利用可能になり、次のように実行します。

モジュール名.関数名(...)

例えば、2つの値の最大公約数を求めるには以下のように記述します。

import math
print(math.gcd(117, 208))
13

math関数の詳細は以下
docs.python.org

❷random
randomのモジュールをimportすれば、ランダム数の簡単に作成できる。

import random
print(random.random())  #0~1未満の浮動小数点を表示
print(random.randint(0, 5))      #0-5までの整数を返す
print(random.randrange(5)) #0-4までの整数を返す
print(numpy.random.rand(n))   #0~1未満の浮動小数点をnで指定した数だけ表示する。一様分布

このとき、乱数の種(seed)を指定すると、必ず同じ乱数になる。以下はシードとして143を与えると、出される乱数は必ず2

import random
random.seed(143)
print(random.randint(1,6))

❸from
fromをつけておくと、省略して書くことができる。
構文は、 from import の順である。たとえば、from datetime import date
(例)

import math
print(math.sqrt(3))
print(math.sin(math.pi/2))

以下はfromを使った場合。math.をつけないのでスッキリする。

from math import sqrt, sin, pi
print(sqrt(3))
print(sin(pi/2))

❹as
numpy(ナムパイ)モジュールを使うと、複雑な数学の計算が行いやすくなる。
暗黙のルールとして、以下のようにimportと、npと名をつける。
import numpy as np

import numpy as np
print(np.exp(1),np.pi,np.cos(np.pi/3),np.log(10))

結果は、以下。
2.718281828459045 3.141592653589793 0.5000000000000001 2.302585092994046
ただ、これは、mathでも同じ

import math
print(math.exp(1),math.pi,math.cos(math.pi/3),math.log(10))
(3)モジュールを作成する

モジュールは、自分で作成することができる。
❶外部から読み込むモジュールを作る
たとえば以下のモジュールをmod1.py とする

def func(name):
    print('hello ' + name +'!')

❷モジュール全体を読み込む場合
メインとなるファイルは以下。importでモジュールmod1を読みこんでいる。

import mod1

mod1.func('taro')

これを実行すると、mod1.pyのfunc関数が呼ばれ、以下が実行される。

hello taro!

少し解説すると、モジュールの中の関数を使うには、モジュールを指定して関数をつける。上記でいうと、mod1.funcである。
注意点は、モジュールをimportで読みこんだ瞬間に、読みこんだプログラムが実行される。
※もちろん、関数であれば、その関数を呼ばなければ実行はされない。

❸モジュールの中の特定の関数だけを呼ぶ場合
先のファイルを以下のように書き換える。mod1というモジュールから、funcだけを呼ぶ。

from mod1 import func

func('taro')

この場合、先と違って、mod1.funcではなく、単にfuncとだけ書けばいい。
また、仮に複数の関数がmod1.pyに記載されていたとしても、funcしか呼ばれていないので、動かない。

(4)パッケージとモジュール

プログラムを部品化してモジュール化したとする。
さらに、そのモジュールをまとめてパッケージにすることができる。
やりかたは簡単で、フォルダを作成し、その中にモジュールとなるファイルを入れるだけ。
たとえば、pkg1というフォルダに、以下のようにファイルを入れる。

+ pkg1
    + mod1.py
    + mod2.py
    + __init__.py

その場合、__init__.py という名前のファイルが、パッケージを含むディレクトリに(基本的には)必要。とりあえず、ファイルは空でも動く。
では、パッケージを読んでみよう。パッケージをモジュールと見ればいいので、構文は同じ。import を使い、フォルダ.ファイル名 で読み込む。

import pkg1.mod1

pkg1.mod1.func('taro')

表記が長いので、asを使って別名を付けると便利だろう。

import pkg1.mod1 as pk11

pk11.func('taro')

14.コマンドライン引数

CやJavaと同じである。コマンドを入力する際に、引数をいくつか渡す。
最初にsysをインポートする。

import sys
print(sys.argv[1])
print(sys.argv[2])

入力された文字は、sys.argvという配列(リスト)に、が格納されている
では、上記に引数を渡して実行してみよう。

#pg1.py 10 25
10
25

つまり、sys.argv[1]には10、sys.argv[2]には25が入っている。
リストに入っていることを確認するために、以下は参考として。

import sys
print(sys.argv[0]) #==>pg1.py
print(sys.argv[1]) #==>10
print(sys.argv[2]) #==>20
print(sys.argv) #==> ['pg1.py', '10', '20']
print(sys.args[1:3]) #==> ['10', '20']