2: 2017-01-07 (土) 07:35:56 njf |
3: 2017-01-10 (火) 10:56:22 njf |
| | | |
| クラスの定義は「class」で行います。 | | クラスの定義は「class」で行います。 |
| + | クラス名の後には「(obect)」を付けます。 |
| + | 古いPythonではこれは必要なく、今でも省略可能ですが、継承などで一部の記法が使えなくなるので付けるようにするのがオススメです。 |
| メソッドの定義は「def」です。 | | メソッドの定義は「def」です。 |
| コンストラクタは「__init__」で、インスタンス化に「new」は不要です。 | | コンストラクタは「__init__」で、インスタンス化に「new」は不要です。 |
| | | |
- | class TestClass: | + | class TestClass(object): |
| def __init__(self): | | def __init__(self): |
| print "construct!" | | print "construct!" |
| 他の言語で言うところの「this」とほぼ同じです。 | | 他の言語で言うところの「this」とほぼ同じです。 |
| | | |
- | class TestClass: | + | class TestClass(obect): |
| | | |
| def whatIsSelf(self): | | def whatIsSelf(self): |
| | | |
| 結果 | | 結果 |
- | <type 'instance'> | + | <class '__main__.TestClass'> |
- | <__main__.TestClass instance at 0x10c2a4bd8> | + | <__main__.TestClass object at 0x10bcdb8d0> |
| | | |
| この「self」を使ってクラス内のメソッドを呼びます。 | | この「self」を使ってクラス内のメソッドを呼びます。 |
| 多くの他言語の「this」と違って、省略することはできません。 | | 多くの他言語の「this」と違って、省略することはできません。 |
| | | |
- | class CallMethod: | + | class CallMethod(obect): |
| def method1(self): | | def method1(self): |
| print "method1 called" | | print "method1 called" |
| クラス変数はクラス名でも「self」を含むインスタンスからでも参照可能です。 | | クラス変数はクラス名でも「self」を含むインスタンスからでも参照可能です。 |
| | | |
- | class ClassVariables: | + | class ClassVariables(obect): |
| a = 1 | | a = 1 |
| b = 2 | | b = 2 |
| print self.b | | print self.b |
| self.a = 10 | | self.a = 10 |
| + | self.c = 11 |
| | | |
| classVariables = ClassVariables() | | classVariables = ClassVariables() |
| print ClassVariables.a | | print ClassVariables.a |
| print classVariables.a | | print classVariables.a |
| + | print classVariables.c |
| 結果 | | 結果 |
| 2 | | 2 |
| 1 | | 1 |
| 10 | | 10 |
| + | 11 |
| | | |
- | ここでインスタンスでそのクラス変数を参照するときには、もしインスタンスでその変数を変更していなければ初期値を参照し、そうでなければ変更後の値を参照します。 | + | ここでインスタンスでそのクラス変数を参照するときには、もしインスタンスでその変数を変更していなければ初期値を参照し、そうでなければ変更後の値を参照します。また、インスタンスの変数はメソッドの中で始めて定義することもできます。 |
| + | |
| + | 言い換えれば、インスタンスの変数はメソッドで代入したときに始めて定義され、その後はクラス変数よりインスタンスの変数を優先して参照すると言うことです。 |
| | | |
| これは他のprototype型のクラス定義を採用している言語と同様です。 | | これは他のprototype型のクラス定義を採用している言語と同様です。 |
| Pythonではprivateなどの参照範囲を制限する修飾子はサポートされていません。 | | Pythonではprivateなどの参照範囲を制限する修飾子はサポートされていません。 |
| 代わりに「_」(アンダーバー)で始まる要素には慣習的にクラス外から参照しない(しようと思えばできる)、「__」(アンダーバー2つ)で始まる要素はクラス外から参照するとエラーになる、という命名ルールがあります。 | | 代わりに「_」(アンダーバー)で始まる要素には慣習的にクラス外から参照しない(しようと思えばできる)、「__」(アンダーバー2つ)で始まる要素はクラス外から参照するとエラーになる、という命名ルールがあります。 |
- | class PrivateMethod: | + | class PrivateMethod(object): |
| def __method(self): | | def __method(self): |
| print "__method" | | print "__method" |
| privateMethod = PrivateMethod() | | privateMethod = PrivateMethod() |
| | | |
- | 「_」で始まるメソッドは参照可能(ただし非推奨)。 | + | 「_」で始まるメソッドは参照可能(ただし慣習的に参照するのは非推奨)。 |
| privateMethod._method() | | privateMethod._method() |
| 結果 | | 結果 |
| __method | | __method |
| | | |
- | 「__」で始まるメソッドはクラス内からの呼び出しは可能ですが、外部から呼び出すとエラー。 | + | 「__」で始まるメソッドはクラス内からの呼び出しは可能ですが、外部から呼び出すとエラーとなります。 |
| privateMethod.__method() | | privateMethod.__method() |
| | | |
| AttributeError: PrivateMethod instance has no attribute '__method' | | AttributeError: PrivateMethod instance has no attribute '__method' |
| | | |
- | &font(Red){制作中}; | + | しかし、実はこれは「__」で始まるメソッドは「_クラス名メソッド名」と名前が変更されるだけなので、実は無理矢理アクセスすることも可能です。 |
| + | |
| + | privateMethod = privateMethod._PrivateMethod__method() |
| + | |
| + | 結果 |
| + | |
| + | __privateMethod |
| + | |
| + | つまり、Pythonには言語仕様として完全にアクセス範囲を制限する機能はありません。 |
| + | そのため、プログラムを無駄に複雑にしないために、なるべく慣習的なスタイルを守るようにしましょう。 |
| | | |
| *継承 [#u224ed0a] | | *継承 [#u224ed0a] |
| + | |
| + | 継承はクラス名の後の「()」の中に親クラスの名前を入れることで行います。 |
| + | 親クラスへのアクセスはそのままクラス名を指定するか、「super」関数を使います。 |
| + | |
| + | class ParentClass(object): |
| + | def __init__(self): |
| + | print "parent" |
| + | |
| + | def printType(self): |
| + | print type(self) |
| + | |
| + | |
| + | class ChildClass(ParentClass): |
| + | |
| + | def __init__(self): |
| + | ParentClass.__init__(self) |
| + | |
| + | def printType(self): |
| + | super(ChildClass,self).printType() |
| + | |
| + | childClass = ChildClass() |
| + | childClass.printType() |
| + | |
| + | 結果 |
| + | parent |
| + | <class '__main__.ChildClass'> |
| + | |
| + | 「super」は親クラスの名前を知らなくても利用できるので、コピペしたときに親を参照したいのに別クラスを参照してしまったというような事故なども防げて何かと便利です。 |
| + | しかし、クラスの定義のところで、「(object)」を付けた方が良いと書きましたが、もしこれを省略すると「super」が使えなくなります。 |
| + | |
| + | つまり「(object)」を指定することで、Pythonのobject型を継承していると判断され、それ特有の関数なども使えるようになるわけです。 |
| + | |
| + | Pythonでは全ての基本的なクラスは「object」を継承しているので、それにならってクラスを自作するときも「object」を継承しておくのがおすすめです。 |
| + | |
| + | ただし、小規模な開発でのクラス定義だと、さほどobjectを継承させるメリットは無いかも知れないので、場合によって調整してください。 |
| + | |
| + | また、Pythonは多重継承もサポートしています |
| + | |
| + | class Class1(Class2,Class3): |
| + | ... |
| + | |
| + | ただし、多重継承は継承関係が複雑化したり名前の衝突が起きやすいことから嫌われる傾向にあります。メリットがはっきりしている場合を除けば避けた方が無難かも知れません。 |
| + | |
| *クラスメソッドとスタティックメソッド [#o110c130] | | *クラスメソッドとスタティックメソッド [#o110c130] |
| + | |
| + | Pythonではクラスメソッドとスタティックメソッドの両方が使えます。 |
| + | |
| + | 記法としては「@classmethod」と「@staticmethod」というアノテーションを使います。 |
| + | |
| + | |
| + | class StaticAndClassMethod(object): |
| + | @classmethod |
| + | def classMethod(cls): |
| + | print "class method" |
| + | |
| + | @staticmethod |
| + | def staticMethod(): |
| + | print "static method" |
| + | |
| + | |
| + | StaticAndClassMethod.classMethod() |
| + | StaticAndClassMethod.staticMethod() |