2

これは、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) のように書こうと思います。

4

2 に答える 2

4

すぐに、これは必要ありません-次のことができるので:

point.x, point.y, point.z = (14, 22, 30)
# Tuple unpacking ... is there nothing it cannot do?

ただし、これは十分に明確ではなく、実際には一度に複数のフィールドを設定できる必要があるとしましょう。次に、使用できます__setitem__

def __setitem__(self, key, value):
    if isinstance(key, tuple):
        for k, v in zip(key, value):
            setattr(self, k, v)
    else:
        setattr(self, key, value)

次に、次のように実行できます。

point['x', 'y', 'z'] = (14, 22, 30)

getprops次に、__getitem__メソッドを同様に実装されたメソッドに置き換えることもできます。

x, y, z = point['x', 'y', 'z']
于 2013-03-15T01:09:38.630 に答える
0

これは、辞書を使用せずにメンバーを動的に追加できる単なるオブジェクトです (引用符を入力するのが嫌いなので)。

あなたの説明で何かを見逃したかもしれませんが、あなたはすでにこれを行うことができませんか? 例えば

class Foo(Object):
    def __init__(self):
        pass

f = Foo()
f.x = 1
f.y = 2
f.z = 3

print f.x, f.y, f.z # outputs 1 2 3

あなたの質問の2番目の部分については、この構文を取得することについて、

point.setprops('x','y','z') = (14, 22, 30)

残念ながら、これが可能かどうかはわかりません。その理由は、

point.setprops('x', 'y', 'z')

'call' 式です。Python が解析される方法のため、割り当てステートメントの左側に call 式を含めることはできないと思います。私の知る限り、変数名またはスライス/インデックス式のリストしか持てません。そうは言っても、100%確信はありません。それを機能させるために実行できるクレイジーな python 忍者がいくつかあるかもしれません。

于 2013-03-14T17:44:27.647 に答える