デコレーターを自作する方法!! part2

takkun
どうも!たっくんです!
久々の更新となってしましたが、、、MHWのHRは100を超えることが出来ました!

以前、関数を使ったデコレーターの自作方法をご紹介しましたが、今回はClassを使ってデコレーターを作る方法をやってみたいと思います∠( ゚д゚)/

デコレーターを自作する方法!!

2018.02.28

書式

Classでデコレーターを作るときの書式は、以下のように「__call__」を作って行きます!

class Decorator(object):
	def __init__(self, func):
		self.func = func

	def __call__(self, *args, **kwargs):
		関数の処理の前にやりたいコトを書く
		try:
			# デコレーターを付けた関数の実行
			return self.func(*args, **kwargs)
			 
		except Exception, e:
			raise
			 
		finally:
			関数の処理の後にやりたいコトを書く

処理の前後に、openChunk・closeChunkを入れる

以前の記事で関数で作成したものを、Classで作成してみたいと思います!ここでは、基本的なものを基底クラス「Decorator」で作成しておき、継承したクラスで「__call__」をオーバーライドしてみます。

from maya import cmds

# デコレーターの基底クラス
class Decorator(object):
	def __init__(self, func):
		self.func = func

	def __call__(self, *args, **kwargs):
		pass
		

# 基底クラスを継承して作成
class CollectHistoryDecorator(Decorator):
	def __call__(self, *args, **kwargs):
		cmds.undoInfo(ock=True)
		try:
			return self.func(*args, **kwargs)
			 
		except Exception, e:
			raise
			 
		finally:
			cmds.undoInfo(cck=True)
			
@CollectHistoryDecorator
def callback():
	# なんらかのツール処理
	# callback()の実行前に、cmds.undoInfo(ock=True)が実行され
	# callback()の実行後に、cmds.undoInfo(cck=True)が実行される。
	pass

クラスを使えば、関数のときより高度なことがいろいろやりやすそうですね!(*´ω`*)b

引数をもたせる

デコレーターそのものに引数を設けて、動作のモードを作ったりしたいときがあると思います。そんな時は、以下のような書式を使っていきます!(*´ω`*)b

class Decorator(object):
	def __init__(self, *args, **kwargs):
		# 引数を受け取り、インスタンス変数に保存
		self.args = args
		self.kwargs = kwargs

	def __call__(self, func):
		def wrapper(*args, **kwargs):
			関数の処理の前にやりたいコトを書く
			try:
				# デコレーターを付けた関数の実行
				return func(*args, **kwargs)
				
			except Exception, e:
				raise
				
			finally:
				 関数の処理の後にやりたいコトを書く
		
		return wrapper

ツールの処理が終わった時に、選択を戻したい

こちらも、以前の記事で関数で作成したものを、Classで作成してみたいと思います!ただ、復元する選択をノードの種類でフィルタリングできるようにしてみます!(*´ω`*)b

from maya import cmds

class PreserveSelectionDecorator(object):
	def __init__(self, filter):
		# 引数を受け取り、インスタンス変数に保存
		self.filter = filter

	def __call__(self, func):
		def wrapper(*args, **kwargs):
			# 設定されたfilterを使って選択をマスクキングして取得
			selection = cmds.ls(sl=True, type=self.filter)
			try:
				# デコレーターを付けた関数の実行
				return func(*args, **kwargs)
				
			except Exception, e:
				raise
				
			finally:
				cmds.select(selection)
		
		return wrapper
		
# transformの選択だけ復元するようにデコレーターを設定する
@PreserveSelectionDecorator('transform')
def main():
	# なんらかのツール処理
	# main()の実行前に、selection = cmds.ls(sl=True, type=self.filter)が実行され
	# main()の実行後に、cmds.select(selection)が実行される。
	pass