6

リストを使用して一連の記述子を参照しようとしましたが、成功しませんでした。記述子 ( ) を介してアクセスしたい_b外部ライブラリ ( ) によって定義されたオブジェクト ( ) のリストがあります。次の例では、記述子への参照のリストが割り当てられますが、リストのいずれかの項目に値が割り当てられると、記述子への参照は値を記述子に渡す代わりに、値によって上書きされます。記述子に関するいくつかの参考文献や記事を読んだ後でも、記述子の基本的な動作が明らかに欠けています。class Aclass Descriptorb

class Descriptor(object):
    def __init__(self, varname):
        self.varname = varname
        pass

    def __get__(self, instance, owner):
        print('get', self.varname)
        #return getattr(getattr(instance, self.varname),"get")()
        return instance.__dict__[self.varname].get()

    def __set__(self, instance, value):
        print('set', self.varname)
        #getattr(getattr(instance, self.varname),"set")(value)
        instance.__dict__[self.varname].set(value)

class A(object):
    def __init__(self, value=None):
        self.value = value
    def get(self):
        return self.value
    def set(self, value):
        self.value = value

class C(object):
    print "root"
    a = Descriptor('_a')
    b = [Descriptor('_b[x]') for x in range(5)]
    def __init__(self, val):
        print "init"
        self._a = A()
        self.a = val
        self._b = [A() for x in range(5)]
        self.b[0] = 1
c = C(3)
d = C(4)

print c._a.get()
print c.a
print d._a.get()
print d.a
print c.b[0]

私の実際のプログラムでは、外部ライブラリは、さまざまなインターフェイスを簡単に交換できるように抽象化したい gui ライブラリです。GUI のいくつかのビューには、プログラムのリストに対応するエントリ ボックスの列 (列ごとに最大 40 個) が含まれています。

また、ディスクリプタに渡されたインスタンス オブジェクトのメンバ関数にアクセスする方法としては、getattrまたは__dict__. __dict__よりきれいに見えますが、それを使用する際にフレームワークや使いやすさの問題があるかどうかはわかりませんでした.

尋ねられた質問に関するヘルプや、プログラムでの私のニーズを満たすための他のアプローチの提案をいただければ幸いです。ありがとう。

ミリムースの推奨に従って、次のリストのようなクラスが私のニーズを満たしているようです。クラスルートで定義されている記述子以外のこのメソッドの落とし穴はあり__init__ますか? 他のリスト関数を追加する必要があり、負のインデックスなどの特別なインデックス動作を追加する必要があります。

class DescriptorList(object):
    def __init__(self, owner, varname):
        self.owner = owner
        self.varname = varname

    def __getitem__(self, index):
        print('getitem', self.varname, index)
        return getattr(getattr(self.owner, self.varname)[index],"get")()

    def __setitem__(self, index, value):
        print('setitem', self.varname, index)
        getattr(getattr(self.owner, self.varname)[index],"set")(value)

class C(object):
    a = Descriptor('_a')
    def __init__(self, val):
        self._a = A()
        self.a = val
        self._b = [A() for x in range(5)]
        self.b = DescriptorList(self, '_b')
        for i in range(5):
            self.b[i] = i

c = C(3)
print [c.b[i] for i in range(5)]

また、 でDescriptorListインスタンス化すると、 がオブジェクトの名前の代わりにオブジェクト自体を使用するC.__init__ように、コードを単純化できます。DescriptorListこの方法に利点または欠点はありますか?

class DescriptorList(object):
    def __init__(self, var):
        self.var = var

    def __getitem__(self, index):
        print('get', self.var, index)
        return self.var[index].get()

    def __setitem__(self, index, value):
        print('set', self.var, index)
        self.var[index].set(value)

class C(object):
    a = Descriptor('_a')
    def __init__(self, val):
        self._a = A()
        self.a = val
        self._b = [A() for x in range(5)]
        self.b = DescriptorList(self._b)
        for i in range(5):
            self.b[i] = i

__get__と の扱いがと と異なる__set__のはなぜですか?__getitem____setitem__

4

2 に答える 2

0

同様のものが必要で、次のことを思いつきました。

class Element(object):
  def __get__(self, obj, objtype=None):
    print("Element.__get__(), obj.idx={0}".format(obj.idx))
    return random.randint(1, 10)

  def __set__(self, obj, value):
    print("Element.__set__(), obj.idx={0}, value={1}".format(obj.idx, value))

class Indexable(object):
  # Can also sub-class from list; I needed mine to be fixed length 
  # because I was mapping them to a set of hardware registers.

  element = Element()

  def __init__(self, sz):
    self.sz = sz
    self.idx = 0

  def __getitem__(self, idx):
    self.idx = idx
    return self.element

  def __setitem__(self, idx, value):
    self.idx = idx
    self.element = element

class Owner(object):
  def __init__(self):
    self.seq = Indexable(5)

random.randint Element.__get__() を呼び出しますが、明らかに、それは任意です。get/set 関数がどのレジスタを読み書きするかを知るために必要だったのはインデックスでした。

于 2013-10-03T17:58:27.243 に答える
0

ミリムースからのフィードバックと、性質が似ている別の投稿に基づいて、次のコードは私のニーズを満たしているように見えますが、少し面倒に思えます。

class Descriptor(object):
    def __init__(self, varname, index=None):
        self.varname = varname
        self.index = index

    def __get__(self, instance, owner):
        print('get', self.varname, self.index)
        if self.index is not None:
            return getattr(getattr(instance, self.varname)[self.index],"get")()
        else:
            return getattr(getattr(instance, self.varname),"get")()

    def __set__(self, instance, value):
        print('set', self.varname, self.index)
        if self.index is not None:
            getattr(getattr(instance, self.varname)[self.index],"set")(value)
        else:
            getattr(getattr(instance, self.varname),"set")(value)

class DescriptorList(list):
    def __init__(self, initlist, instance):
        self.instance = instance
        super(DescriptorList,self).__init__(initlist)

    def __getitem__(self, index):
        print('getitem', self.instance, index)
        return super(DescriptorList,self).__getitem__(index).__get__(self.instance, self.instance.__class__)

    def __setitem__(self, index, value):
        print('setitem', self.instance, index, value)
        super(DescriptorList,self).__getitem__(index).__set__(self.instance, value)

class A(object):
    def __init__(self, value=None):
        self.value = value
    def get(self):
        return self.value
    def set(self, value):
        self.value = value

class C(object):
    a = Descriptor('_a')
    b = [Descriptor('_b', x) for x in range(5)]

    def __init__(self, val):
        self._a = A()
        self.a = val
        self._b = [A() for x in range(5)]
        self.b = DescriptorList(self.__class__.b, self)
        for i in range(5):
            self.b[i] = i*val

c = C(3)
d = C(4)
print c.a
print d.a
print [c.b[i] for i in range(5)]
print [d.b[i] for i in range(5)]

このソリューションの制限やエラー、または提案された改善についてのコメントをお待ちしております。

于 2012-11-19T21:12:33.463 に答える