これは、Python 構文でできることについての楽しい質問です。
matlab から python に移行したときに、matlab の構造体と同じように動作するクラスを作成しました。
class DynStruct(AbstractPrintable):
' dynamical add and remove members '
def __init__(self, child_exclude_list=[]):
super(DynStruct, self).__init__(child_exclude_list)
これは、辞書を使用せずにメンバーを動的に追加できる単なるオブジェクトです (引用符を入力するのが嫌いなので)。
また、IPython で作業しているときに何をしているかを確認できるように、クラスのメンバーを適切に出力するクールなヘルパー クラスも作成しました。(インポートは省略していますが、標準的なものと派手なものだけです)
class AbstractPrintable(object):
'A base class that prints its attributes instead of the memory address'
def __init__(self, child_print_exclude=[]):
self._printable_exclude = ['_printable_exclude'] + child_print_exclude
def __str__(self):
head = printableType(self)
body = self.printable_attributes()
body = re.sub('\n *\n *\n','\n\n',body)
return head+('\n'+body).replace('\n','\n ')
def printable_attributes(self, type_bit=True):
body = ''
attri_list = []
for key in self.__dict__.iterkeys():
if key in self._printable_exclude: continue
val = self.__dict__[key]
namestr = str(key)
valstr = printableVal(val)
typestr = printableType(val)
max_valstr = 10000
if len(valstr) > max_valstr:
valstr = valstr[0:max_valstr/2]+valstr[-max_valstr/2:-1]
attri_list.append( (typestr, namestr, valstr) )
attri_list.sort()
for (typestr, namestr, valstr) in attri_list:
entrytail = '\n' if valstr.count('\n') <= 1 else '\n\n'
typestr2 = typestr+' ' if type_bit else ''
body += typestr2 + namestr + ' = ' + valstr + entrytail
return body
#---------------
def printableType(val):
if type(val) == numpy.ndarray:
info = npArrInfo(val)
_typestr = info.dtypestr
elif isinstance(val, object):
_typestr = val.__class__.__name__
else:
_typestr = str(type(val))
_typestr = _typestr.replace('type','')
_typestr = re.sub('[\'><]','',_typestr)
_typestr = re.sub(' *',' ',_typestr)
_typestr = _typestr.strip()
return _typestr
次に、DynStruct から多数の要素を取得する必要がある場合があったため、必要な要素のタプルを返す関数を追加しました。
# I added this function to DynStruct
def getprops(self, *prop_list):
return tuple([self.__dict__[prop_name] for prop_name in prop_list])
例えば:
>> point = DynStruct()
>> point.x = 3
>> point.y = 1
>> point.z = 60
>> print point
DynStruct
int x = 3
int y = 1
int z = 60
>> # Now I want to get the points
>> (x,y,z) = point.getprops('x','y','z')
さて、これはうまく機能し、デバッグが非常に簡単になります。しかし、一度にたくさんのプロパティを設定したい場合がありました (上記のようなものです)。これを行うには他の方法があることはわかっていますが、構文が次のように機能する setprop が本当に欲しいです。
point.setprops('x','y','z') = (14, 22, 30)
よくわかりませんが、 @someobj.setter デコレータのおかげでこれを行う方法があるように感じます。しかし、等号演算子をオーバーロードしてこのように使用する方法、またはそれが可能かどうかはわかりません。
当面は point.setprops('x','y','z', 14, 22, 30) のように書こうと思います。