こんにちは。薬学長です。
今回は、Pythonの基本講座➄ということで始めていきましょう。
25. オブジェクト指向
クラスの定義
classクラス名:
“””ドキュメンテーション文字列”””
defメソッド名 (self,…):
class Prius:
maker = “Hitati”
type = “Gear”
type_1 = “Gear1”
#クラスと、その プロパティ の「 maker」「 type」「 type_1」を定義しています。
def my_func (self):
クラスのメソッド
myJob = Doctor()
# インスタンス変数名 = とすることで、 インスタンスが作成 されます( Doctor() でも OK)
print(myJob.maker )
# インスタンス名 プロパティ名とすることで、 プロパティ の値が表示されます。
mySecondJob = Instructer()
※新たにインスタンスを作成することもできます。
classes = [“apple”, “pain”, car]
myFamilyCar= classes[2]()
print(myFamilyCar.maker )
※Hitatiと表示
myFamilyCar.my_func()
※myFamilyCar インスタンスの my_func 関数を実行する
クラス変数、インスタンス変数
pythonには、クラスで定義する属性として、クラス変数とインスタンス変数があります。
■クラス変数とは
➀オブジェクト同士で共有することができる変数
➁メソッドの内部でなく、クラスの直下に記載
クラス変数にアクセスの仕方
クラス名.クラス変数名
インスタンス名.__class__. クラス変数名
■インスタンス変数とは
➀インスタンスごとに別々に利用する変数
➁メソッドの内部に記載
インスタンス変数にアクセスするには、
インスタンス名,変数
コンストラクタ __init__
オブジェクトをインスタンス化する際に呼び出されるメソッドをコンストラクタと言います。
python の場合、__init__ というメソッドを作成すれば、インスタンス作成時に自動的に呼び出されます。
例えば、クラスのプロパティを初期化する際などに、コンストラクタを利用すると便利です。
class sample_class :
def __init__ (self, msg):
print(“コンストラクタが呼び出されます “)
self.msg = msg
※プロパティ msg をコンストラクタの引数 msg で初期化します。
def print_msg (self):
print(self.msg)
※プロパティ msg を表示します。
sample =sample_class (“Hello“, )
※インスタンス作成時にコンストラクタ init が実行されます。
※”コンストラクタが呼び出されましたと表示されたのち、プロパティ msg に ”Hello” が格納されます。
sample.print_msg()
※インスタンス sample の print_msg メソッドを実行します。
プロパティ msg は “Hello”なので、 print(self.msg) で “Hello” と表示されます。
デストラクタ
デストラクタ__del__ を定義すると、インスタンスを削除する際に呼び出されます。
class del_sample:
def __del__(self):
print(“delが呼び出されました。 “)
del1 =del_sample ()
del del1
※delインスタン名とすると、インスタンスが削除されます。
※インスタンスを削除すると、 __ del__が呼び出され、 “del が呼び出されました。 “が表示されます。
26. インスタンスメソッド、クラスメソッド、スタティックメソッド
Pythonのクラスのメソッドには、インスタンスメソッド、クラスメソッド、スタティックメソッドの3種類があります。
インスタンスメソッドとは
クラスから作成したオブジェクト(インスタンス)を用いて呼び出すメソッド
インスタンスメソッドの例
class MyClass
def init __( name):
self.name=name
def print_hello (self)
※インスタンスメソッド
print(‘Hello’+ self.name)
AClass = MyClass (‘World’)
AClass.print_hello()
引数のself は必ずつけます。 self は自分自身(作成したインスタンス自身を表し、
例の場合だとコンストラクタで初期化した、インスタンス変数 name を呼び出しています (self.name)
クラスメソッドとは
クラスメソッドの例 「classmetthod」 をつけます
class MyClass
class_name=’myclass’
def init __( name):
self.name = name
@classmethod
def print_hello(cls):
print(‘Hello’ + cls.class_name)
MyClass.print_hello()
➀@classmethod で定義
➁第一引数をcls を取ります(cls はクラス自身)
cls.変数名とすることで、クラス変数に アクセスできます。
初期化(インスタンス化)がされていないため、インスタンス変数に アクセスすることはできません
スタティックメソッドとは
インスタンスメソッドやクラスメソッドのようにインスタンスやクラスが引数に渡されること
はしません。
スタティックメソッドの例 @staticmetthod をつけます
class MyClass:
class_name = ‘myclass’
def __init__ (self,name):
self.name=name
@staticmethod
def print_hello():
print(‘Hello World”)
MyClass.print_hello()
➀@staticmethod で定義
➁クラス変数へもインスタンス変数へもアクセスできない
ちなみに、インスタンスからクラスメソッド、スタティックメソッドを利用することはできる
特殊メソッド
https://docs.python.org/ja/3/reference/datamodel.html
詳細は上記ヘルプサイトから参照
特殊メソッドはインスタンスにアクセスする際に、特定の処理を実行すると呼び出されるメソッド。
例えばa + b として実行するとき、内部的には a.__add__ (b) として呼び出される。
以下に特殊なメソッドを記します。
__str__:
※str(object), print(object) の際に呼び出され、オブジェクトを文字列として返す
__bool__:
※if 文で論理値を返すことができる
__len __:
※len 実行時に呼び出される。
__eq__:
※== の際に呼び出される
__hash__:
※文字列をハッシュ値として返す。この関数を定義することで、クラスを辞書として扱うときや
set に要素を入れるさいに利用する
__name__:
※クラスの名前を表す
27. オブジェクト指向
継承
ある別のクラスからそのクラスの持っている性質を引き継ぐこと。車というクラスから軽自動車とい
うクラスを新たに作る場合を継承という。この場合、軽自動車というクラスには車クラスと同じ プロパ
ティ 、メソッド を引き継ぐことができる。この場合継承元のクラスをスーパークラス、継承先にクラスをサブクラスと言う。
ポリモーフィズム
サブクラスを複数作成して、サブクラスごとに同じ名前のメソッドをそれぞれ作成して、
処理の中身を変える。呼び出す際には、中身を意識せずに実行できる性質のこと
クラスの継承
クラスを継承する場合には、classクラス名(継承先): と記述します
class Person:
※「人」クラス人としての機能(プロパティ、メソッド)を持つ
def init (self, name, age):
self.name = name
self.age = age
def greeting(self):
print(“Hello! I’m {}”.format(self.name))
def breathing(self):
print(“su-ha –“)
class Employee(Person):
※クラス Person を継承すると、親クラスのプロパティ(name,age)、メソッド(greeting,breathing)を Employee クラスのもののように自由に扱えるようになります。
def __init__ (self, name, age, number):
super().init (name, age)
super()とすることで、親クラスを呼び出し、 __init__で name と age を初期化できます。
self.number= number
def greeting(self):
print(“Hello Sir My name is {}. number is {}”.format(self.name,self.number )) # greetingをオーバーライドして、 新たなメソッドとして定義しています。
※オーバーロード は引数や返り値が異なるが名称が同一のメソッドを複数定義すること
(Python でオーバロードはできません)
def greeting(self, msg):
def serve(self):
pass
※Employeeクラスで serve メソッドを新たに定義します。ここでは、詳細は省略します。
28. クラスの多重継承
クラスを多重継承する場合には、classクラス名(継承先 1, 継承先 2): と記述します
class ClassA :
def __init__ (self, name):
self.a_name = name
def print_a (self):
print(“a = {}”.format(self.a_name ))
def print_hi (self):
print(“A hi”)
class ClassB
def __init__ (self, name):
self.b_name = name
def print_b (self):
print(“b = {}”.format(self.b_name ))
def print_hi (self):
print(“B hi”)
class NewClass (ClassA , ClassB ):
def __init__ (self, a_name , b_name , name):
ClassA init (self, a_name )
※親クラス ClassA の初期化
ClassB init (self, b_name )
※親クラス ClassB の初期化
self.name = name
def print_name (self):
print(“name = {}”.format(self.name))
メタクラス
ポリモーフィズムに先立ってメタクラスについて説明します。
メタクラスとは、クラスの再定義をするクラスという風に考えればよいです。
(デフォルトのメタクラスは type クラスだが、自身で定義することもできる)
class定義時に、継承と同じ形で metaclass メタクラス名とすると自身のメタクラスを指定できます
メタクラスは、主にその定義でよいのかクラスを検証する際に用いられます。
定義は以下のようにします
class Meta(type):
def __new__(metacls , name, bases, class_dict):
※クラスのチェックを行う
※name:クラスの名前
※bases:継承しているクラス
※class_dict クラスの持っている値
return super().__new__(metacls,name,bases,class_dict)
※type クラスでクラスを生成する
ポリモーフィズム 多態性
サブクラスを複数作成し、同じメソッドを定義して呼び出す際にどのクラスか意識せずに呼び出すこと
from abc import abstractmethod ABCMeta
class Human( metaclass ABCMeta)
※親クラス
def __init __(self. name):
self.name = name
@abstractmethod
※親クラスでは処理を定義しないメソッド。
子クラスで必ずオーバーライドする(オーバーライドしないと ABCMeta にはじかれる)
def say_something (self):
pass
def say_name (self):
※共通メソッド
print(self.name)
class HumanA (Human):
def say_something (self)
print(“I’m A”)
class HumanB (self):
def say_something (self):
※同じ名前のものを定義
print(“I’m B”)
Private 変数
これまで学んだクラス変数、インスタンス変数は外部からアクセス して値を書き換えられます。
そのため、アクセスの出来ない変数(Private 変数を定義する必要があります)
ただし、 Pythonは厳密なPrivate 変数は存在しないので、以下の方法でも外部からアクセスできます
__variable
※Private 変数 アンダースコア を二つ付けて定義
class Human:
__msg = “Hello”
※クラス変数の Private 変数
def __init (self, name,
self.__name = name
self.__age = age
※インスタンス変数の Private 変数です。
def print_msg (self):
print(“{} name = {}, age = {}”.format(self.__msg , self.__name , self.__age ))
※クラス内でアクセス
tanaka = Human(“Tanaka”, 25, ‘Man’)
seiya = Human(“Seiya”, 27, ‘Man’)
print(tanaka.__name)
※これはアクセスできずエラーになります。
print(tanaka._Human__name)
※Private変数ですが、クラス外からも普通にアクセスできます。
カプセル化, setter,Private
Private変数を使う場合には、クラスの外部から変数が見えないようにする(カプセル化)必要があります。カプセル化をする場合には、 getter と setter を定義して利用しないと変数にアクセスができないようにします。
【カプセル化の方法 1 】
def get_変数名():
def set_変数名():
変数名= property(get_変数名,set_変数名)
class Human:
def init (self, name,age):
self.__name = name
self.__age = age
def get_name (self):
※__nameのgetterの定義
print(“getterを呼び出します”)
return self.__name
※private 変数の __name を返します。
def get_age (self):
return self.__age
def set_name (self, value):
※__name の setter の定義
print(“setterを呼び出します”)
self.__name = value
※private 変数の __name を設定します。
def set_age (self,value)
self.__age = value
name = property(get_name , set_name )
※property 関数を利用することで、get_name と set_name を呼び出す機能を持った
name プロパティが作成されます。
age = property(get_age , set_age)
カプセル化 setter, getter
【カプセル化の方法 2 】
@property,@var.setter
class Human:
def init (self, name,age):
self.__name = name
self.__age = age
@property
※@propertyとすると、 name プロパティの getter として定義します
def name(self):
print(“getterを呼び出します”)
return self.__name
※private の変数、 __name を返します。
@property
def age(self):
return self.__age
@name.setter
※name プロパティの setter として定義します。
def name(self, value):
print(“setterを呼び出します”)
self.__name = value
※private の変数、 __name を設定します
@age.setter
def age(self, value):
self.__age = value
29. ファイル入力
ファイルからのテキストの読込みは以下のコマンドを利用する
f = open(file_path , mode=”r”)
※読込みモード
line = f.read ()
※ファイルの中身全体を読込み
f.close()
※ファイルを閉じる
f = open(file_path , mode=”r”, encoding =”utf-8″)
※utf 8 でファイルを開く
f = open(file_path , mode=”r”, encoding =”sjis”)
※shift jis でファイルを開く
f = open(file_path , mode=”r”, encoding = “\r\n”)
※改行コードを\r\nに指定(crlf)
lines = f.readlines ()
※行ごとに分割したリストとして取得
line = f.readline ()
※ファイルを一行毎に読込み
➀read, readlines はファイルを全て一気に読み込むため、処理は速いがメモリの消費は大きい(小さいファイル向け)
➁readline はファイルを 1 行ずつ読み込むため、処理は遅いがメモリの消費は小さい(大きいファイル向け)
ファイルのopen と close を自動的に行う (with)
with open(file_path , mode=”r”) as f:
for x in f.readlines():
・・・・
with 構文を抜けると自動的にファイルがクローズされる
セイウチ演算子に行う
with open(‘file.csv’, mode=’r’) as f:
while msg f.readline():
print(msg)
30. ファイル出力
ファイル書き込み
f = open(file_path , mode=”w”)
※書き込みモード(ファイルが存在しなければ作成、存在した場合は上書き)
f.write(文字列)
※ファイルに文字列を書き込み(\nで改行)
f.close()
※ファイルを閉じる
f.writelines()
※リストをそのままつなげて書き込み
f.write(‘\n’,join(list))
※リストを改行させて書き込み
with open(file_path , mode=’w’,’\r\n’, encoding = ‘sjis’) as f:
※ファイル追記
f = open(file_path , mode=”a”)
※追記モード ファイルが存在しなければ作成、存在した場合は追記
バイナリファイルの読み書き(詳細は割愛)
modeにbを付ける
open(file_path,mode =’rb’)
※バイナリファイルの読み込み
open(file_path,mode = ‘wb’)
※バイナリファイルの書き込み
28. with 詳細
withの基本的な使い方について記載します。 with は以下のように記述します。
withクラス as a:
処理
withの中の処理を実行する前に、 with の後に指定したクラスの __init と __enter_ がそれぞれ呼ばれ、処理終了後に、クラスの __exit__ メソッドが呼ばれます。
withをどのように使うかというと、処理が連続していてすべての処理が必要な場合、例えば
•ファイルの書き込み処理(ファイル開く→書き込む→ファイル閉じる)
•DB へのデータの書き込み処理 (DB へコネクションを張る→書き込む→コネクションを閉じる)
class WithTest (object):
def init (self):
print(“init が呼ばれました”)
def__enter__(self):
print(“enterが呼ばれました”)
def__exit__(self,exc_type,exc_val,exc_tb):
print(“exitが呼ばれました”)
with WithTest() as t:
print(“withを実行しました”)
※withでクラスを作成すると、まず__init__を実行、次に __enter__ を実行、処理終了後に、__exit__ を実行します。
※以下の順で実行されます。
※init が呼ばれました
※enter が呼ばれました
※with を実行しました
※exit が呼ばれました
大変お疲れさまでした。以上でPythonの基礎講座は終了です。
早速、これらの基本技能を生かしてアプリ開発やデータ分析を行っていきましょう。