通常の状況では、クラスを定義してクラスのインスタンスを作成するときに、任意のプロパティとメソッドをインスタンスにバインドできます。これは、動的言語の柔軟性です。
最初にクラスを定義する
class Student(object):
pass
次に、プロパティをインスタンスにバインドしてみます。
>>> s = Student()
>>> s.name = 'Michael' # 动态给实例绑定一个属性
>>> print(s.name)
Michael
メソッドをインスタンスにバインドすることもできます。
>>>def set_age(self, age): # 定义一个函数作为实例方法
> self.age = age
>>> from types import MethodType
>>>s.set_age = MethodType(set_age, s) # 给实例绑定一个方法
>>>s.set_age(25) # 调用实例方法
>>>s.age # 测试结果
>25
ただし、あるインスタンスにバインドされたメソッドは、別のインスタンスには影響しません。
>>> s2 = Student() # 创建新的实例
>>> s2.set_age(25) # 尝试调用方法
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'set_age'
メソッドをすべてのインスタンスにバインドするために、メソッドをクラスにバインドできます。
>>>def set_score(self, score):
> self.score = score
>
>>>student.set_score = set_score
メソッドをクラスにバインドした後、すべてのインスタンスを呼び出すことができます。
>>> s.set_score(100)
>>> s.score
100
>>> s2.set_score(99)
>>> s2.score
99
通常の状況では、上記のset_scoreメソッドはクラスで直接定義できますが、動的バインディングを使用すると、プログラムの実行中にクラスに関数を動的に追加できます。これは、静的言語で実装するのが困難です。
__slots__を使用する
しかし、インスタンスのプロパティを制限したい場合はどうでしょうか?たとえば、Studentインスタンスに追加できるのはname属性とage属性のみです。
制限の目的を達成するために、Pythonでは、クラスを定義するときに特別な__slots__変数を定義して、クラスインスタンスに追加できる属性を制限することができます。
class Student(object):
__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
次に、次のことを試みます。
>>> s = Student() # 创建新的实例
>>> s.name = 'Michael' # 绑定属性'name'
>>> s.age = 25 # 绑定属性'age'
>>> s.score = 99 # 绑定属性'score'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'
'score'は__slots__に配置されていないため、score属性をバインドできません。scoreをバインドしようとすると、AttributeErrorエラーが発生します。
__slots__を使用する場合、__ slots__で定義された属性は現在のクラスインスタンスにのみ影響し、継承されたサブクラスには影響しないことに注意してください。
>>> class GraduateStudent(Student):
... pass
...
>>> g = GraduateStudent()
>>> g.score = 9999
__slots__もサブクラスで定義されていない限り、このように、サブクラスインスタンスに許可される属性は、それ自体の__slots__と親クラスの__slots__です。