2017年3月15日水曜日

Python 3 Object-oriented Programming 2 , Dusty Phillips 2章

Notebook

Python 3 Object Oriented Programming でオブジェクト指向を勉強する.Chap.1ではいろいろと用語が書かれているが,これだけ読んでも仕方ないので実際にコードを書きつつ覚えていくことにする.こちらを読むと理解が早まる(ような気がする).

Chap.2 Objects in Python

Creating Python classes

In [1]:
class MyFirstClass: # クラス名はCamelCaseで書く
    pass
# 最小のクラス


a = MyFirstClass()
b = MyFirstClass() # こんな感じでインスタンス化(instantiate)

print(a)
print(b) # インスタンスの番地を書き出す
# a, b の番地が異なるから,a, bが異なったオブジェクトとわかる.
<__main__.MyFirstClass object at 0x7f5c9c77b320>
<__main__.MyFirstClass object at 0x7f5c9c77b438>

In [2]:
class Point:
    pass # 構造は MyFirstClassと同じ

p1 = Point()
p2 = Point()

p1.x = 5 # .フニフニでフニフニという属性をインスタンスに作成し,値を代入できる.
p1.y = 4 # <object>.<attribute> = <value>   dot notation という.

p2.x = 3
p2.y = 6

print(p1.x, p1.y) # .フニフニでインスタンスを属性を参照もできる.
print(p2.x, p2.y)
5 4
3 6

Making it do somethin

クラスに属性だけでなく振る舞(method)いを与える.インスタンスに対して何かをするための何か.

In [3]:
class Point:
    def reset(self): # 関数定義と全く同じ書き方だが,selfという引数が必ず必要.クラス定義内で書くとmethod定義になる.
        self.x = 0 
        self.y = 0
        
p = Point()
p.reset() # <instance>.<method> で<instance>に<method>を適用する.selfは書かない.
print(p.x, p.y)
0 0

methodの引数selfは,あるインスタンスでmethodが呼ばれた時,そのインスタンスを指す.
instance.method() のカッコの中にPythonがselfを補う.
instance.method() はClass.method(instance) と同値.

More arguments

instance.method(arg1, arg2, ...)で,引数を渡せる.

In [4]:
import math
class Point:
    def move(self, x, y): # 引数を取れる point.move(x, y) か Point.move(point, x, y) で呼べる.
        self.x = x
        self.y = y
        
    def reset(self):
        self.move(0, 0)
        
    def calculate_distance(self, other_point):
        return math.sqrt(
                    (self.x - other_point.x)**2 +
                    (self.y - other_point.y)**2)
    
point1 = Point()
point2 = Point()

point1.reset()
point2.move(5, 0)
print(point2.calculate_distance(point1))
Point.move(point1, 3, 4) # point1.move(3, 4) と同値
print(point2.calculate_distance(point1)) 
5.0
4.47213595499958

Initializing the object

インスタンスを定義した時に,属性に値を定める.

In [5]:
class Point:
    def __init__(self, x, y): #__init__というメソッドが,インスタンス定義の際に実行される
        self.move(x, y) #__init__ の引数にデフォルトを定めることも可能
        
    def move(self, x, y):
        self.x = x
        self.y = y
        
    def reset(self):
        self.move(0, 0)
        

point = Point(3, 5)
print(point.x, point.y)
3 5

In [6]:
point = Point() # __init__ で指定した引数と,インスタンスを定義するときに渡す引数が異なるとエラー
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-64a9ffbe9de0> in <module>()
----> 1 point = Point() # __init__ で指定した引数と,インスタンスを定義するときに渡す引数が異なるとエラー

TypeError: __init__() missing 2 required positional arguments: 'x' and 'y'
Explaining yourself

クラスやクラス内のメソッドでも''' docstring ''' が使える

Modules and packages

他の.pyファイルをモジュールとして読み込める.モジュール読み込みには幾つかの種類がある.
database.py というファイルがあって,中にDatabase というクラスや関数が定義されている時,

import database
db = database.Database()

で,databaseモジュールをインポートして使える.モジュールのある一つのクラスだけを使いたいときは

from database import Database
db = Database()

とも書ける.さらにasでモジュール自体やモジュールの中身に別名をつけて,名前の重複や長い名前を避けれる.

import numpy as np
from database import Database as DB
db = DB()

以下略

Who can access my data?

pythonは他の多くの言語と違って属性やメソッドにアクセス制限を設けておらず, . を名前の前につけることで,クラス内部でのみ利用されるもので,外からアクセスしないことを推奨する目印にしている.特に外からのアクセスを拒みたいときは, _. を名前の前につける.
instance.__attribute ではアクセスできないが, instance._class__attribute で結局アクセスできるので,特に意味はない.

2章 以下略