mathjax

2013年9月10日火曜日

PEOPLE_2: 質点のクラス(part 1)

PEOPLE_2: 質点のクラス(part 1)

ソースファイル

前回、質点を「質量を持ち、その存在位置以外に自由度を持たない物体」と定義した。 今回からは、この定義をPythonのクラスとして表現する事を試みる。

「質量を持ち」について。

普通は、ある一定の質量を持ち、という意味である。つまり、これは質点の自由度ではなく、個々の質点に固有の値である。

この事を考慮した質点クラスの定義を行う。それにはプロパティを用いるのが良い。

質点クラスの定義

In [1]:
class PointMass(object):
    def __init__(self,sitsuryo=1.0):
        self.__mass=sitsuryo
    @property
    def mass(self):
        return self.__mass

クラス定義の解説

クラスの定義の仕方は、上記の様に

class クラス名(継承する元のクラス):

とする。この時、既存のクラスの定義を引き継いで再利用する場合には括弧内に引き継ぐ(継承する)元のクラス名を書くのだが、今回は特に無い。 その場合、括弧内にはobjectという最も基本となるクラスを継承する。

また、

@property

はデコレータと呼ばれる文で、これによって、直後の関数定義がこのクラスに属するオブジェクトのプロパティと呼ばれる変数になる。

今回の場合、直後に

def mass()

によってmassという関数が定義されているが、これは実際にはPointMassというクラスのmassというプロパティを定義している事になる。

オブジェクト指向プログラミングを知らない人の為に、 クラスの使用方法と、プロパティの使用例を以下に示す。

質点オブジェクトの生成

In [2]:
pm1=PointMass()
pm2=PointMass(2.0)

解説

pm1=PointMass()

これで、pm1という名前を持ち、PointMassというクラスに属するオブジェクトが作られる。具体的には、PointMassの定義の中にある、

__init__(self,sitsuryo=1.0)

が実行される。その際、sitsuryoという引数には1.0というデフォルトの数値が代入される。

pm2=PointMass(2.0)

こちらの方が一般的な方法で、この場合にはsitsuryo=2.0という数値を用いて、__init__()が実行される。

selfというのは、オブジェクト自身を表す引数で、__init__()の中身を見ると、

self.__mass=sitsuryo

とあるが、これは例えば、pm1というオブジェクトに__massという変数が定義され、そこに先ほどのsitsuryoという引数を代入せよという意味になる。

その後、この__massという値はpm1のプロパティであるmassという変数の呼び出し命令によって呼び出される事になる。

つまり、外部からみると、pm1はmassというプロパティを持っているが、内部では__massという名前の変数として扱っている。

その様子を以下で見てみる。

質量の読み出し(呼び出し)

In [3]:
print pm1.mass
print pm2.mass
1.0
2.0

In [4]:
print pm1.__mass
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-947959c917a9> in <module>()
----> 1 print pm1.__mass

AttributeError: 'PointMass' object has no attribute '__mass'

PointMassというクラスのオブジェクトは__massという変数を持っていない

というエラーメッセージが出るはずである。

* (「__massという変数にはアクセスできない」というメッセージでないのは一見不思議だが、pythonでは他の多くのプログラミング言語とは異なり、オブジェクト変数に対する本当の意味でのアクセス制限は行わない。その代わりに、オブジェクト変数の名前を自動的に複雑化する事でアクセスを難しくしている。 この手法を Name Manglingと呼んでいる。) *

このように、外部からは__massという変数は見えない。

また、sitsuryoという変数も見えない。 こちらは__init__という関数の内部でのみ使われているローカルな変数で、オブジェクトの変数ですらない。

In [5]:
pm1.sitsuryo
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-cf74258e4a57> in <module>()
----> 1 pm1.sitsuryo

AttributeError: 'PointMass' object has no attribute 'sitsuryo'

質量の不変性

質量の変更を試みる。

In [6]:
pm1.mass=3.0
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-9b92080ef8e1> in <module>()
----> 1 pm1.mass=3.0

AttributeError: can't set attribute

変更はできない。これによって、質点の質量は不変ということになる。

次に、質量というプロパティそのものを消してみる。

In [7]:
del pm1.mass
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-7-8c8d28d11d94> in <module>()
----> 1 del pm1.mass

AttributeError: can't delete attribute

これによって、質量を持たない質点は存在できない。

個々の質点そのものなら消すことができる。

In [8]:
del pm1

まとめ

プロパティというのはオブジェクトが持っている変数の一種だが、そのアクセス方法はクラス定義の内部の関数によって定義されている。 今回の場合、massというプロパティは読み出す(呼び出す)方法だけを定義したので、設定(つまり値を変更)したり、削除したりすることは出来ない。

このような性質は一定の質量を持つ質点の定義方法として適切であろう。

0 件のコメント:

コメントを投稿