理系母の趣味はプログラミング

理系院卒、メーカー技術職の二児の母が、PythonやVBAで色々と作ってアップしていくブログです。

【20日目】オブジェクト指向プログラミング④抽象化について学ぶ

こんばんは、なぺです。
今日はオブジェクト指向プログラミングの4大要素のうちの2つ目、抽象化について学びます。
今回は短くなりそう

まず、抽象化とは

抽象化とは、対象から細部や具体性を取り去り、本質的に重要な要素や、着目している側面のみを取り出して、一つの概念として定義すること。また、異なる複数の対象に共通する性質や要素を見出し、共通点を組み合わせて汎用的な概念を構成すること。

e-words.jp


ということです。
要は、大事なところだけ残す、ということでしょうか?

本では人をモデル化することを例にとって追加説明がありました。

人の特徴には、髪の色、目の色、身長、体重、民族、性別、など、多くの複雑な要素があります。しかし、人をクラスで表現しようとしたとき、多くの特徴はこのクラスで扱いたい問題に関係ありません。

わかった気がする!

ここから私の考え

例えば、
全国一斉学力テストを実施した。
その結果のうち数学と理科について、県、市町村別に比較したい。
Personクラスに人のインスタンスを定義したいとき。

この時のコードは下記のようになると思われる。

>>> class Person:
	def __init__(self,m,s,p,c):
		self.math = m
		self.science = s
		self.pref = p
		self.city = c
person1 = Person(90,50,'tokyo','minatoku')

やりたいことは、「数学と理科について、県、市町村別に比較したい」なので、
インスタンス変数にはmath、science、pref(市)、city(区市町村)しか設定しない。
それ以外の、国語や英語の点数、学校名、性別、髪の色、目の色、身長、体重、民族、などはやりたいことに関係ないので、情報として破棄します。

これが抽象化。

だよね?


間違ってたら教えてください!

今日は以上です。

参考書はこちらです。

それでは、また^^

【19日目】オブジェクト指向プログラミング③カプセル化について知る

こんばんは、なぺです。
前回、オブジェクト指向プログラミングの書き方を学びました。
オブジェクト指向プログラミングには、カプセル化、抽象化、ポリモーフィズム、継承という4つの主要な概念があります。
今回はそのうちの一つ、カプセル化を学びます。

カプセル化には2つの概念があります。

一つ目は「オブジェクトによって複数の変数(状態を保持します)とメソッド(状態を変更したり状態を使用して計算したりします)をまとめること」です。

例えば前回書いた下記のコード

class Rectangle():
    def __init__(self, w, l): #1
        self.width = w
        self.len = l

    def area(self): #2
        return self.width * self.len

    def change_size(self, w, l): 
        self.width = w 
        self.len = l 

#1のところでは、複数の変数(wとl )がインスタンス変数として保持されています。
#2のところでは、オブジェクトの状態を使用して面積を計算するメソッドを定義しています。
これらがオブジェクトの単位にまとめられています。これがカプセル化です。

2つ目は、「データをクラス内に隠蔽して外から見えないようにすること」です。
クラスの中のデータは、メソッドを通じて操作させるようにすることで、外から隠蔽してしまいます。


ん?でもたしか、インスタンス変数って、"オブジェクト.インスタンス変数=xxx"と書けば直接書き換えられたような…。
と思ったのですが、どうやらタプルのように変更不可なデータを設定することで、直接書き換えられないようにできるみたいです。
となるとメソッドを通じてでないと、データ変更不可となります。

ここでpython先輩に物申す。

「でもPython先輩、メソッド使えば書き換えられるんですよね?
それじゃカプセル化って言わないじゃないですか。
他のプログラミング言語さん方はプライベート変数やプライベートメソッドを定義して外側から書き換えられないようにしてるらしいっすよ。」

するとPython先輩、こう答えました。

「確かに、私にプライベートはない。常にパブリックだ。だからメソッドとか変数名の前にアンダースコア(_)つけてたら、それには触れてはいけないという決まりを作った。もし使ったら、どうなっても自己責任な^^」

えー!

どうやら
_unsafe_method(self) のように、メソッド名の前にアンダースコアがついている場合、それには触ってはいけないという、暗黙のルールがあるみたいです。
使えるっちゃ使えるけど、保証外ですと、自己責任だと。

どうせなら使えなくしてほしい…。(てか使えなくする方法ないの...?)
なんか腑に落ちないけど、これがカプセル化らしいです。

今日は以上です。
文章だらけになってしまった

参考書はこちらです。

それではまた^^

【18日目】オブジェクト指向プログラミング②メソッドを追加する

こんばんは、なぺです。
昨日からオブジェクト指向の理解に心折れかけています。
今日も苦しいですが、よろしくお願いします。

さて、前回はクラスを定義し、__init__という特殊メソッドを使ってオブジェクト(インスタンス)を生成しました。
今回は、メソッドを追加で定義する方法を学びます。

長方形を表すクラスを生成してみます。

class Rectangle():
    def __init__(self, w, l):
        self.width = w
        self.len = l

rectangle = Rectangle(10, 20)
print(rectangle.width)
print(rectangle.len)

#出力結果
10
20

幅10、長さ20の長方形(rectangleオブジェクト)ができました。

では、長方形の面積を返すメソッドを追加します。
面積をリターンさせます。

class Rectangle():
    def __init__(self, w, l):
        self.width = w
        self.len = l

    def area(self): #メソッドを追加
        return self.width * self.len  #面積をリターンさせる

rectangle = Rectangle(10, 20)
print(rectangle.area())
#出力結果
200

rectangleオブジェクトを作った際に、self.widthとself.lenにはそれぞれ値が格納させているため、self.width * self.len をreturnさせることで面積が計算できます。
追加したメソッドは、オブジェクト名.メソッド名()で呼び出すことができます。

次に、長方形のサイズを変更するメソッドを追加します。
インスタンス変数wとlを更新するということ。

class Rectangle():
    def __init__(self, w, l):
        self.width = w
        self.len = l

    def area(self):
        return self.width * self.len

    def change_size(self, w, l):  #サイズ変更のメソッドを追加
        self.width = w #wを更新
        self.len = l #lを更新

rectangle = Rectangle(10, 20)
rectangle.change_size(20, 40) 
print(rectangle.width)
print(rectangle.len)

#出力結果
20
40

できました!

手の込んだプログラムを書く時には、このオブジェクト指向プログラミングというやり方が良いみたいですが、まだ「ふーん」レベルです。
後ほどそれが実感できるといいな(笑)

今日は以上です。

参考書はこちらです。


それではまた^^

【17日目】オブジェクト指向プログラミング①とりあえずやってみる

こんばんは、なぺです。

今回からPart2に入ります!
今日の内容は、プログラミングパラダイムについて。
プログラミングパラダイムとは、プログラミングのスタイル、手法のことらしいです。

手続き型プログラミング、関数型プログラミングオブジェクト指向プログラミングと3種類が本では紹介されています。
今まで学んできたやり方は、手続き型プログラミングだったようです。

しかし、もっとPythonを極めるには、オブジェクト指向プログラミングを学ぶ必要があるということなので、それについて記事にまとめようと思います。

オブジェクト指向プログラミング
そもそもオブジェクトってなに?
調べました。

オブジェクトとは、物、物体、目標物、対象、目的語、客体、などの意味を持つ英単語。

ほお。

本を読み進めます。

オブジェクト指向プログラミングでは、オブジェクトに状態を持たせます。


ふむふむ。
わかったようでわからないけれど、とりあえず読み進めます。

オブジェクト指向プログラミングでは、複数のクラスで相互に作用するオブジェクトの集合を定義します。クラスは表現したいオブジェクトを定義・分類するプログラミングの仕組みです。

ふむう。

すべてのオブジェクトはクラスのインスタンスです。

ふむ。

いや、まあね、クラスとかインスタンスとか、FEで勉強したから何となく知ってますよ。
私の場合、クラス:人間 インスタンス:なぺ みたいな感じでしょ?
でも「知る」と「腑に落ちる」は違うのね。
私のそれは「知る」だったのね。

こういうときは実際に手を動かすに限る。

人間クラスを定義してみます。

 class Human: #クラスを定義
	def __init__(self): #initメソッドを定義
		print("Created!")

Pythonの慣習として
・クラス名は大文字で始める
・__init__の第一引数にはselfを使う
があります。
__init__はインスタンス変数を定義する特別なメソッドです(init=initializeの略)
この__init__のように、二重のアンダースコアで囲まれたメソッドは、特殊メソッドといいます。

うーん。
すみません。難しいのでとりあえず覚えときます。
だんだんわかってくるかな…

次に、私のインスタンスを定義してみます。

class Human:
	def __init__(self,k,n):
		self.kuni=k
		self.name=n
		print("Created!")
  hito1 = Human("nihon","nape")
#出力結果↓
Created!

これで私なぺのインスタンスが生成されました。
プリントしてみると

print(hito1)
#出力結果↓
<__main__.Human object at 0x0000017292022948>

hito1オブジェクト自体を出力すると、hito1がHumanクラスのオブジェクトであることと、コンピュータのメモリ上の位置を返します。

インスタンス変数の値が知りたい場合、下記のようにします。

print(hito1.kuni)
#出力結果
nihon

また、オブジェクトは複数作ることもできて

class Human:
    def __init__(self,k,n):
        self.kuni = k
        self.name = n
        print("Created!")

hito1 = Human("nihon","nape")
hito2 = Human("USA", "Tom")
hito3 = Human("Kenya","mukamikamau")
#出力結果
Created!
Created!
Created!

オブジェクトを指定して出力できます。

print(hito2.name)
#出力結果
Tom

息切れしそう…
ここ、初心者のぶちあたる壁なんじゃないか?
少なくとも私はぶち当たりました…。TT

今日はここまで~

難しい~

それではまたTT

【16日目】ファイル操作③CSVファイルを読み書きする

こんばんは、なぺです。
今日はファイル操作の最後、CSVファイルを扱います。
産休前は何かとお世話になっていたCSVファイル。
いずれはエクセルとも連携したいし、きっと大事だよね。

ということでまずはCSVについてちゃんと知ることから。

CSVはComma Separated Values=カンマで区切られた値、の略語です。
その名の通り、中身はカンマで区切られたデータです。

one, two, three
for, five, six

こんなの

では、PythonCSVファイルを作ってみます。
CSVを扱うときは、組み込みモジュールCSVを使います。

import csv #csv組み込みモジュールを使わせて宣言

with open("test.csv", "w",newline="") as f:   #newline=""がないと行間が一行分空く
    w = csv.writer(f, delimiter=",") #ファイルオブジェクトfを、デリミタ=","でcsv化しwに格納
    w.writerow(["one","two","three"]) #リストをCSVに1行分書き出す
    w.writerow(["four","five","six"]) #リストをCSVに1行分書き出す

test.csvというcsvファイルを出力することができました。
エクセルで開くと、

one two three
four five six

と、一つずつ、セルに入った状態になっております。

open関数のオプション引数newline=""についてはよくわかりませんでしたが、これなしで実行すると、one, two, three,とfour,five,sixの間に空の行が一行分挿入されてしまったので、指定したほうがいいみたいです。
また、writerowは一行の書き出ししか行わないので、出力したい行数分繰り返す必要があります。多分ループとか使ってうまくやるのだろう…。

出力の次は、読み込みます。

前回やったのと同じで、open関数の第二引数に"r"を指定します。

import csv #csv組み込みモジュールを使わせて宣言

with open("test.csv", "r") as f:#読み込みモード引数に"r"を指定
    r = csv.reader(f, delimiter=",") #ファイルオブジェクトfを、デリミタ=","で呼び出し、wに格納
    for row in r: #rの要素分ループする。ループする度に変数rowに要素を格納
        print(",".join(row)) #rowに格納された要素を","をはさんで出力

#出力結果↓
one,two,three
four,five,six


カンマで区切られた文字列を出力できました!
いつかCSVで書かれたデータベースを扱うときに使えますように!


CSVは以上です。
参考書でいうと、次はハングマンという吊られた人の絵が出てくるおどろおどろしいゲームを作るのですが、
今までのまとめなので、割愛します。

独学プログラマーのpart1が終わりました!
次はpart2です。


参考書はこちらです。

それではまた^^

【15日目】ファイル操作②open関数でファイルを読み書きする

こんばんは、なぺです。
今日はファイル操作の二回目です。
今日はファイルの読み書きをPythonでやってみます。

ファイルの読み書きにはopen関数を使います。

open("ファイルパス", "モード")

モードにはファイルを開くときにどのように動作するべきかを決定する文字を入れます。

  • ”r"  読み込み専用
  • "w"  書き出し専用
  • "w+" 読み書き両方可

open関数は、ファイルオブジェクトと言われるオブジェクトを返します。

・ファイルに書き込む
モード="w"のとき、新しいファイルを作ります。

ファイルオブジェクトに書き込むにはwriteメソッドです。

では早速、ファイルを新規作成して書き込んでみます!
ファイルパスの部分はセキュリティ上載せておりませんよ!

file = open('ファイルパス\\hoge.txt','w')
file.write("i can do it!")

指定したディレクトリを実際に見に行って確認する。
お、あったあった、hoge.txtが新しくできておる!
どれどれ、中身は…
あれれ~白紙だよ?
"i can do it!"と書き込んだはずなのに…。

はい、実は本のコードを省略していました。すみません。
ファイルに書き終わったらcloseメソッドを使ってファイルを閉じる必要があるみたいです。
複数のファイルを開いた後に閉じるのを忘れてしまうと、プログラムがうまく動作しないことがあるらしいです。
「まあ、複数のファイル開いてないし、大丈夫でしょ!」
と考えてcloseメソッドを省略しましたが、ダメでしたね。

ということでまじめにcloseメソッドを追加。

file = open('ファイルパス\\hoge.txt','w')
file.write("i can do it!")
file.close()

できました!i can do it!とメモ帳に入力されてました。

ちなみに日本語などの「非アスキー文字」を書き込む場合、open関数の引数として、ファイルの文字コードを指定したほうがいいらしいのですが…

試しに日本語を入力してみたところ文字コード指定なしで普通に入力できてしまったので、必要不可欠ってわけではなさそう…

file = open('ファイルパス\\nihongo.txt','w')
file.write("日本語ですYO")
file.close()
file = open('ファイルパス\\nihongo.txt','w',encoding="utf-8")
file.write("日本語ですYO")
file.close()

上記どちらもちゃんと書き込めてました。
まあでも、非アスキー文字を扱うときは念のため指定したほうがよさそうですね~。

ところで非アスキー文字ってなんぞ

調べました。

ASCII文字とは、文字コードの標準規格として広く普及している「ASCII」(American Standard Code for Information Interchange、アスキー)に含まれる文字のこと。
いわゆる半角の英字(a~z、A~Z)やアラビア数字(0~9)、記号、空白文字、制御文字など128文字が規定されている。アクセント記号などの付いた文字や、ギリシャ文字キリル文字などラテン文字以外のアルファベット、漢字、仮名、ハングル、タイ文字など非欧米圏の文字、いわゆる全角英数字、全角記号、ローマ数字、顔文字などはASCII文字には含まれない。

引用元↓
e-words.jp


ふむふむ。
プログラミングに使われる文字はアスキー文字。
それ以外は非アスキー文字なのかな?

うん、了解です。

・ファイルを自動的に閉じる
ファイルに書き込む際は、開いた後に閉じることを忘れないことが大事であることがわかりました。
そこで便利な方法としてファイルの閉じ忘れ防止の構文があるらしいです。
えー!じゃあこっちだけ覚えればいいじゃーん!そゆこと早く言って~
とか思ってしまってごめんなさい。

早速使ってみます。

with open("hogehoge.txt","w") as f:
    f.write("hogehoge~hogehoge~!")

できました。構文は下記

with open([ファイルパス], [モード]) as [変数名]:
[コード]

変数名 にはファイルオブジェクトを割り当てる変数名を書きます。
コード にはファイルオブジェクトにどうするか書きます。

withのブロック中のコードをすべて実行し終えると、Python先輩がファイルをそっと閉じてくれます。うれしい!

・ファイルを読み込む
やることは二つ。
1.open関数の引数[モード]の部分に、読み込みを指定する文字"r"を指定する
2.readメソッドを呼び出す。
です。

with open("hogehoge.txt","r") as f:
    print(f.read())

#出力結果
hogehoge~hogehoge~!

日本語も出力してみよう

with open("nihongo.txt","r") as f:
    print(f.read())

#出力結果
譌・譛ャ隱槭□YO

ぎやゃぁぁぁぁ
化けたあああ

文字化け嫌い。

「まあでも、非アスキー文字を扱うときは念のため指定したほうがよさそうですね~。」
とか言って軽く見てましたすみません。

ちゃんと文字コードは指定しましょう。

with open("nihongo.txt","r", encoding="utf-8") as f:
    print(f.read())

#出力結果
日本語だYO

ほっ
できました。

今回はうまくいきましたが、WindowsではシフトJISでファイルが書かれている場合が多いらしく、その場合、encoding="cp932"と指定したほうがいいみたいです。
ただ、私もWindowsですがcp932と指定すると化けました。
よくわからないです。知ってる人教えてください。

今日は以上です!
明日はCSVファイルを扱いますよー!

それではまた^^

【14日目】ファイル操作①どんなOSでも動作するファイルパスを組み立てる

こんばんは、なぺです。
今日も独学プログラマーで勉強します。

今回は、ファイルの操作についてです。
Pythonの外側にでていく感じが中級者ぽくてイイですね。

・ファイルパスは組み立てるもの
ファイルを扱うには、ファイルの住所であるファイルパスを扱えなければなりません。
しかし、ファイルパスの表し方は、OSによって違うらしいのです!
Windowsでは、ファイルの区切りにバックスラッシュ(\)を使いますが、macではスラッシュ(/) なのです。
ということは、バックスラッシュで区切ったファイルパスが記述してあるプログラムは、Windowsでは動くのに、Macではエラーがでた、なんてことが起こり得ます。

これを防ぐために、ファイルパスはPythonに組み立ててもらいます。
osモジュールのos.path.join関数を使えば、複数のフォルダ名を引数として受け取り、そのフォルダ名からパスを組み立てることができます。

>>> import os
>>> os.path.join("Users","nap","st.txt")
'Users\\nap\\st.txt'

あれれ~?
バックスラッシュが二つ重なってるよ~(\\)
aaa\bbb\ccc.txtの形式に慣れているので違和感。

本当にあるフォルダを使ってファイルパスを組み立てて確かめてみる。
すると、ちゃんとファイルが開けました^^
なんで二つ重ねるの??と考えてみると
\はエスケープ文字のため、\一本だけだとエスケープされてしまう。だから二つ重ねるのだ!
と自分の中ではこの説で納得したのですが、勘違いしてたらご指摘ください!

今日は疲れたので終わります。

毎日少しでも更新するのが目標^^

今日で14日目ということで2週間過ぎましたが
二週間だけでもPythonにだいぶ慣れたような気がしてます(ポジティブ)

ちなみに使ってる教材はこちら。


それではまた^^