Python - クラス - プロパティ

公開日:2019-03-04 更新日:2019-05-29
[Python]

1. 概要

プロパティ(クラスのデータ)の使い方です。

2.1 サンプル

クラスに speed と言うプロパティを定義して、クラスの利用者側から値の設定と取得を行っています。

class Car:
	def __init__(self):
		self.speed = 0

car = Car()
print( car.speed )
car.speed = 100
print( car.speed )
0
100

2.2 メソッドからプロパティを使う

同じクラスのメソッドからプロパティを参照する場合は、メソッドの第1引数の self を使います。
self は自動的に渡されるため、メソッドの呼び出し側での指定は不要です。
self を付けないと、メソッド内のローカル変数扱いとなり、メソッドから抜けると破棄されます。

class Car:
	def __init__(self):
		self.speed = 0

	def speed_up(self):
		self.speed += 10

car = Car()
car.speed_up()
car.speed_up()
car.speed_up()

print( car.speed )
30

2.3 プロパティの動的追加

クラスの利用者側からプロパティの追加をしています。
インスタンスに関する追加情報を、元のクラスを変更せずに付与できます。

動的に外部から追加されるプロパティは、基本的にはクラス側では知りえないため、
クラス側からは使用しないプロパティになります。
class Car:
	pass


car = Car()
car.note = "フェラーリ"

car2 = Car()
car2.note = "ポルシェ"

carList = [car, car2]

for c in [car, car2]:
	print( c.note )
フェラーリ
ポルシェ

2.4 読み取り専用プロパティ

メソッドの前に @property を付けると、メソッドをプロパティのように、()を付けずに使用することができます。

クラス内の変数を直接公開した場合との違い
・読み取り専用にできる。
・プロパティの値が取得される際に、処理を実行することができる。

class Car:
	def __init__(self):
		self._speed = 100

	@property
	def speed(self):
		return self._speed


car = Car()
print(car.speed)

#エラー。設定はできない。
#car.speed = 150

100

2.5 書き込み可のプロパティ

メソッドの前に @プロパティ名.setter を付けると、書き込み可のプロパティになります。
読み取り専用プロパティと書き方が異なるため要注意。
プロパティに代入された値は、setter を付けたメソッドの2番目の引数で取得できます。

class Car:
	def __init__(self):
		self._speed = 100
	
	@property
	def speed(self):
		print("speed の取得")
		return self._speed

	@speed.setter
	def speed(self, value):
		print("speed の設定")
		self._speed = value


car = Car()
print(car.speed)

car.speed = 200
print(car.speed)
speed の取得
100
speed の設定
speed の取得
200

2.6 property() を使ったプロパティの定義

property()を使うと、@property や @プロパティ名.setter を使わずにプロパティを定義できます。
定義方法は、getter、setter に該当するメソッドを、property() に渡して、プロパティの変数に設定するだけです。
getter、setter よりも下に定義する必要があるので要注意。
以下では setter も設定していますが、getter だけにすることもできます。
class Car:
	def __init__(self):
		self._speed = 100
	
	def get_speed(self):
		print("speed の取得")
		return self._speed
	
	def set_speed(self, value):
		print("speed の設定")
		self._speed = value
	
	speed = property(get_speed, set_speed)


car = Car()
print(car.speed)

car.speed = 200
print(car.speed)
speed の取得
100
speed の設定
speed の取得
200

2.7 privateプロパティ(プロパティの隠蔽)

Python にはアクセス修飾子(public, private)がありません。
外部から隠蔽したい場合には、変数名の先頭に __ を付けます。
但し、これでも完全ではなく、「_クラス名__プロパティ名」と言う名前で外部からアクセスできます。
dir() で名前の確認ができます(dir はディレクトリとは関係ありません)

また慣例で、変数名の先頭に _ を付けて、private である意志表示をします。
あくまでも意志表示のため、そのまま外部からアクセス可能です。
class Car:
	def __init__(self):
	self.__speed = 100


car = Car()

#エラー。AttributeError
#print(car.__speed)

#オブジェクトのメンバリストの表示
print(dir(car))

#隠蔽されたプロパティの取得
print(car._Car__speed)
car._Car__speed = 200
['_Car__speed', '__class__', '__delattr__', '__dict__', '__dir__', 
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', 
'__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', 
'__lt__', '__module__', '__ne__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__weakref__']
100