クラス
クラスとは
クラスは、変数と関数をまとめたものです。
クラスに属する関数をメソッドと言います。
通常、クラスはインスタンスと呼ばれる実体を作成してメソッドの実行や、
変数への代入を行います。
ただし、クラス変数はインスタンスを作成しなくても参照・代入が可能です。
ひとつのクラスに対して、インスタンスはいくつでも作成可能です。
複数作られたインスタンスは、それぞれ別々の実体として
メソッドの実行・変数への代入などを行うことができます。
メソッドのないクラスを作ると、C 言語の構造体のように扱うことができます。
継承することによって親クラスの変数・メソッドを受け継いで、
新たなクラスを作ることができます。
- クラスは class によって定義されます。
-
class クラス名([親クラス名, ...]):
クラス変数 = 初期値
.
.
def メソッド名(self, ...):
クラス名.クラス変数 = 値
self.クラス変数 = 値
self.インスタンス変数 = 値
内部変数 = 値
その他の Python 文•式
.
.
.
.
- クラス名の頭文字は、通常大文字にします。
- メソッドには、引数として自分自身を表す変数が第一引数に必要です。
通常、self という名前の変数を使います。
- メソッドはクラスのインスタンスを作成して実行します。
- 親クラスを継承している場合は、親クラスのメソッドを上書きして処理を変更することができます。
- クラス変数は、インスタンスを作らなくても参照・代入できます。
クラス名.クラス変数名
という形で使用すると、各インスタンスに共通の変数として使うことができます。
また、self.クラス変数名
という形で使用すると、各インスタンスの内部だけの変数として使うことができます。
- インスタンスを作成してから使えるようになる変数をインスタンス変数と言います。
インスタンス変数は、self.変数名 という形で使用します。
クラスで定義されているメソッドの中ならどこでも使用できます。
- 内部変数は、メソッドの内部で定義される変数で、
定義されたメソッドの内部でだけ有効です。
- 変数名の先頭に_ (アンダースコア)が1つついていると、その変数はクラスの外部から書き換えてはならないルールがあります。
- 変数名の先頭に__ (アンダースコア)が2つついていると、その変数はクラスの外部からアクセスできなくなります。
新スタイルクラス
クラスを定義するとき、継承する親クラス名をつけないと古いスタイルクラスになります。
class myClass1():
def test():
print 'hello'
継承するクラス名として、objeict を指定すると新しいスタイルクラスになります。
class myClass2(object):
def test():
print 'hello hello'
新しいスタイルクラスの方が機能が豊富で便利なので、
現在は新しいスタイルクラスを使うのが一般的です。
特殊なメソッド
クラス内で、以下の名前のメソッドを定義すると特別な意味になります。
- __init__(self, ...)
- クラスのインスタンスが作成されるときに実行されます。
コンストラクタと呼びます。
引数には、インスタンス作成時につけられた引数が渡ります。
- __getattr__(self, name)
- インスタンスの中に name という名前の変数が見つからなかったときに実行されます。
- __getattribute__(self, name)
- インスタンス中の name という名前の変数を参照したときに実行されます。
新スタイルクラスでのみ有効です。
- __setattr__(self, name, value)
- インスタンス中の name という名前の変数に value を代入したときに実行されます。
クラスの例
簡単な例で、クラスの機能を試して見ましょう。
例 1
最初に、hello World と表示するクラスを作ってみます。
例 2
helloWorld1 を元にして、インスタンス作成時に hello World の表示回数と、
後ろに追加する文字列を指定できるようにしてみましょう。
さらに、何も実行しない bye() というメソッドを追加します。
- 以下の Python スクリプトを helloWorld2.py という名前で保存します。
class helloWorld2(object):
def __init__(self, num=1, s=''):
self.rep = num
self.str1 = s
def hello(self):
for i in range(self.rep):
print 'hello World ' + self.str1
def bye(self):
pass # pass は何も実行しません
- スクリプト エディタ の によって helloWorld1.py を読み込んで、テンキーの Enter キーなどで実行します。
- 以下のようにスクリプト エディタのインプットウインドウに入力してみます。
>>> obj2 = helloWorld2(2) # helloWorld2 のインスタンスを作成(num に 2 が代入されて、s はデフォールトの '')
>>> obj2.hello() # hello() メソッドを実行
hello World
hello World
>>> obj2.rep = 3 # インスタンス変数 rep に 3 を代入
>>> obj2.hello() # hello() メソッドを実行
hello World
hello World
hello World
>>> obj2.str1 = 'to you' # インスタンス変数 str1 に 'to you' を代入
>>> obj2.hello() # hello() メソッドを実行
hello World to you
hello World to you
hello World to you
>>> obj2.bye() # bye() メソッドを実行
>>> # 何も実行されません
例 3
helloWorld2 を継承した helloWorld3 というクラスを作って、
bye() というメソッドを上書きし、
byebye() というメソッドを追加してみます。
- 以下の Python スクリプトを helloWorld3.py という名前で保存します。
class helloWorld2(object):
def __init__(self, num=1, s=''):
self.rep = num
self.str1 = s
def hello(self):
for i in range(self.rep):
print 'hello World ' + self.str1
def bye(self):
pass
class helloWorld3(helloWorld2):
def __init__(self, num=1, s1='', s2= ''):
helloWorld2.__init__(self, num, s1)
self.str2 = s2
def bye(self):
for i in range(self.rep):
print 'good bye World ' + self.str1 + self.str2
def byebye(self):
for i in range(self.rep):
print 'bye bye ' + self.str1 + self.str2
- スクリプト エディタ の によって helloWorld1.py を読み込んで、テンキーの Enter キーなどで実行します。
- 以下のようにスクリプト エディタのインプットウインドウに入力してみます。
>>> obj3 = helloWorld3(2, s2=' and I') # helloWorld3 のインスタンスを作成
>>> obj3.hello() # helloWorld2 の hello() メソッドを実行
hello World
hello World
>>> obj3.str2 # helloWorld3 の インスタンス変数 str2 を表示
' and I'
>>> obj3.bye() # helloWorld3 の bye() メソッドを実行
good bye World and I
good bye World and I
>>> obj3.str1 = 'you' # helloWorld2 の インスタンス変数 str1 に 'you' を代入
>>> obj3.rep = 3 # helloWorld2 の インスタンス変数 rep に 3 を代入
>>> obj3.bye() # helloWorld3 の bye() メソッドを実行
good bye World you and I
good bye World you and I
good bye World you and I
>>> obj3.byebye() # helloWorld3 の byebye() メソッドを実行
bye bye World you and I
bye bye World you and I
bye bye World you and I
クラスの使用例
さまざまなオブジェクトを作成して、横に並べるクラスを作ってみましょう。
- 以下の Python スクリプトを makeObjects1.py という名前で作ります。
import pymel.core
class MakeObjects1(object):
__commandName = {'sphere': pymel.core.sphere,
'cone': pymel.core.cone,
'cylinder': pymel.core.cylinder}
def __init__(self, num=1, name='sphere'):
self.num = num
self.com = name
def make(self):
for i in range(self.num):
MakeObjects1.__commandName[self.com]()
pymel.core.move([2*i, 0, 0])
- スクリプト エディタ の によって makeObjects1.py を読み込んで、テンキーの Enter キーなどで実行します。
- スクリプト エディタ のインプットウインドウで以下のように実行してみます。
>>> mobj = MakeObjects1()
>>> mobj.make()
- 次に、作成された球体を消去して、
スクリプト エディタ のインプットウインドウで以下のように実行してみます。
>>> mobj.num = 3
>>> mobj.make()
- もう一度、作成された球体を消去して、
スクリプト エディタ のインプットウインドウで以下のように実行してみます。
>>> mobj.com = 'cone'
>>> mobj.make()
スクリプトの解説
import pymel.core
- Maya モジュールをインポートします。
class MakeObjects1(object):
- MakeObjects1 という名前のクラスの定義です。
object を継承しているので新しいクラス定義になっています。
__commandName = {'sphere': pymel.core.sphere,
'cone': pymel.core.cone,
'cylinder': pymel.core.cylinder}
- クラス変数 __commandName を初期化しています。
代入しているのは、作成するオブジェクトの名前を表す文字列をキーとする
辞書型です。
要素の値は、関数がそのまま入っています。
__commandName は名前の前に __ (アンダースコア 2 つ)が付いているので、
クラスやインスタンスから直接参照・代入はできません。
クラスや、インスタンスから直接、参照・代入されたくない変数に
このような __ (アンダースコア 2 つ)付の変数名を使います。
def __init__(self, num=1, name='sphere'):
- クラスのインスタンスが作られるときに、
実行されるメソッドです。
引数は、num が作成されるオブジェクトの数、
name がオブジェクトをあらわす名前です。
もし、このクラスのインスタンスを作成するときに、
引数を与えないと、num=1, name='sphere' で初期化されます。
たとえば、以下のように実行できます。
obj1 = MakeObjects1() # num=1, name='sphere' で初期化
obj2 = MakeObjects1(3) # num=3, name='sphere' で初期化
obj3 = MakeObjects1(name='cone') # num=1, name='cone' で初期化
obj4 = MakeObjects1(name='cylinder', num=2) # num=2, name='cylinder' で初期化
self.num = num
- インスタンス変数 self.num にオブジェクトの数を代入します。
self.com = name
- インスタンス変数 self.com に作成するオブジェクトの名前を代入します。
def make(self):
- make という名前のメソッドの定義です。
for i in range(self.num):
- self.num 回だけ for 文を繰り返します。
MakeObjects1.__commandName[self.com]()
- __commandName[self.com] に入っている関数を実行します。
もし、self.com に 'sphere' が入っていれば、
pymel.core.sphere() が実行されます。
pymel.core.move(2*i, 0, 0)
- 作成したオブジェクトを X 方向に 2*i だけ移動します。
名前を間違った場合
MakeObjects1 は com にオブジェクト名を代入することによって、
作成するオブジェクトの種類を変えることができるようになっていますが、
com に __commandName に無い名前を代入するとエラーになります。
この場合に、エラーを表示しないで、間違った名前を代入しようとしたら
無視できるようにしておくと便利です。
(練習 2 を参照)
>>> mobj1 = MakeObjects1()
>>> mobj1.com = 'cone' # 正しいオブジェクト名
>>> mobj1.make() # コーンが作成されます
>>> mobj1.com = 'polyCone' # 間違ったオブジェクト名
>>> mobj1.make() # 間違った名前で作成しようとするとエラーが表示されます。
# エラー: ('polyCone',)
# Traceback (most recent call last):
# File "<:maya console>", line 1, in <:module>
# File "<:maya console>", line 12, in make
# KeyError: ('polyCone',) #
練習
- 上の makeObjects1.py を参考にして MakeObjects2.py という Python スクリプトを作り、
メソッド addCommand() , printCommands() を追加して、
作成できるオブジェクトの種類を増やしたり、
現在作成できるオブジェクトの種類を表示できるようにしてみましょう。
- printCommands(self)
- 実行すると以下のように表示されます。
>>> mobj2 = MakeObjects2()
>>> mobj2.printCommands()
sphere
cylinder
cone
- addCommand(self, name, com)
-
- name
- 追加するオブジェクトの名前(文字列)
- com
- 追加するオブジェクトを作成する関数
以下のように実行します。
>>> mobj2 = MakeObjects2()
>>> mobj2.addCommand('polySphere', pymel.core.polySphere)
>>> mobj2.com = 'polySphere'
>>> mobj2.make() # ポリゴンの球体が作成されます
- 上の makeObjects2.py を参考にして makeObjects3.py という Python スクリプトを作り、
com に間違った名前を代入しようとしても代入できないようにしてみましょう。
(実行例)
>>> mobj3 = MakeObjects3()
>>> mobj3.com = 'cone' # 正しいオブジェクト名
>>> mobj3.make() # コーンが作成されます
>>> mobj3.com = 'torus' # 間違ったオブジェクト名
Not found torus # エラーメッセージを表示
>>> mobj3.make() # 'torus' を無視してコーンが作成されます
(ヒント)
- __setattr__(self, name, value) メソッドを追加します。
- 辞書型にキーが含まれているかどうかは、辞書型の has_key() メソッドで調べます。
- __setattr__() メソッドの最後で
self.__dict__[name] = value
を実行しておきます。
これによって、name という変数に value が代入されます。
まとめ
- クラスは class によって定義します。
- クラスは、インスタンスを作成することによってメソッドの実行・変数への代入などを行います。
- クラスの中で定義される変数には、クラス変数・インスタンス変数・内部変数があります。
参考
Prev | Next
Home | Contents
Mail