2017-02-07 8 views
0

したがって、辞書型の値と遅延評価されたプロパティが混在するクラスを実装しようとしています。私は文法上、クラスから__getitem____getattr__経由でアイテムにアクセスし、同じ方法でそれらの値を設定することができますが、whenとsettersのプロパティを使用しています。プロパティを持つクラスの__getattr__と__setattr__メソッドをオーバーライドする

いくつかの私はこれを実装想定する方法のコード例:

class C(object):  
    def __init__(self): 
     self.data = {'akey':'avalue'} 
     self.att1 = '1st attribute' 
     self._prop1 = None 

    def __getitem__(self,key): 
     try: 
      self.__dict__[key] 
     except KeyError: 
      return self.data[key] 

    def __setitem__(self,key,val): 
     self.data[key] = val 

    def __getattr__(self,name): 
     try: 
      self.__dict__[name] 
     except KeyError: 
      return self.data[name] 

    def __setattr__(self,name,val): 
     try: 
      self.__dict__[name] = val 
     except KeyError: 
      self.data[name] = val 

    @property 
    def prop1(self): 
     #do expensive stuff here in real class 
     return self._prop1 
    @prop1.setter 
    def prop1(self,newval): 
     #check/change value for prop1 
     self._prop1 = str(newval).upper() 

属性へのアクセスは、プロパティではなく__getitem__方法のために正常に動作します。

In [35]: c = C() 
In [36]: c.prop1 
Out[36]: 'Prop1 Calc Value' 

In [37]: c['prop1'] 
--------------------------------------------------------------------------- 
KeyError         Traceback (most recent call last) 
C:\Users\someuser\somepath\foo.py in __getitem__(self, key) 
     8   try: 
----> 9    self.__dict__[key] 
    10   except KeyError: 

KeyError: 'prop1' 

During handling of the above exception, another exception occurred: 

KeyError         Traceback (most recent call last) 
C:\Users\someuser\somepath\foo.py in <module>() 
----> 1 c['prop1'] 

C:\Users\someuser\somepath\foo.py in __getitem__(self, key) 
     9    self.__dict__[key] 
    10   except KeyError: 
---> 11    return self.data[key] 
    12 
    13  def __setitem__(self,key,val): 

KeyError: 'prop1' 

は、私は完全に@propertyデコレータはクラスでどのように機能するかを理解していないためであると仮定したが、この問題を解決するための慣用的な方法がある場合、私はそれを聞くのが大好きです!私はそれが本当に構文的な砂糖だと知っていますが、クラスのための柔軟な属性アクセスを持っていて、有効なPython変数名ではないキーをサポートすることができればうれしいです。 pandas.DataFrame/collections.namedtuple apiはこれのインスピレーションです。次のコードは、私のシステム(のpython 3.5)上で動作し、正しい方向に私を指しているため@Jim Fasarakis・ヒリアードへ

Thansk:

編集

作業溶液

class C(object):  
    def __init__(self): 
     self.data = {'akey':'avalue'} 
     self.att1 = '1st attribute' 
     self._prop1 = None 

    def __getitem__(self,key): 
     try: 
      return self.__dict__[key] 
     except KeyError: 
      try: 
       return getattr(type(self), key).__get__(self) 
      except AttributeError: 
       return self.data[key] 
    __getattr__ = __getitem__ 

    def __setitem__(self,key,value): 
     #note order is look for property 1st so that any 
     #setter methods get used insead of attribute access 
     try: 
      getattr(type(self), key).__set__(self,value) 
     except AttributeError: 
      try: 
       self.__dict__[key] = value 
      except KeyError: 
       self.data[key] = value 

    __setattr__ = __setitem__ 

    @property 
    def prop1(self): 
     #do expensive stuff here in real class 
     if not self._prop1: 
      self._prop1='Prop1 Calc Value' 
     return self._prop1 
    @prop1.setter 
    def prop1(self,newval): 
     #check/change value for prop1 
     print('using setter') 
     self._prop1 = str(newval).upper() 

In [62]: c = C() 

In [63]: c['prop1'] 
Out[63]: 'Prop1 Calc Value' 

In [64]: c['prop1'] = 'new value' 
using setter 

In [65]: c['prop1'] 
Out[65]: 'NEW VALUE' 

In [66]: c.akey 
Out[66]: 'avalue' 

In [67]: c.att1 
Out[67]: '1st attribute' 

答えて

1

私はあなたのインスタンスが添え字表記によって記述子にアクセスできるようにしたいと思っています。私はあなたがこれまで何をしているのかはわかりませんが、プロパティはクラスの名前空間にありますので、そこを見る必要があります。

ちょうどそれを試してみて、クラスの辞書からディスクリプタを取得し、起動します。

def __getitem__(self,key): 
    try: 
     return self.__dict__[key] 
    except KeyError: 
     try: 
      return getattr(type(self), key).__get__(self) 
     except KeyError: 
      return self.data[key] 

を次に、あなたが何を望むかを行うことができます(私は推測):

>>> c = C() 
>>> c['prop1'] 
'prop1' 
+0

は私が前に言ったように、それは本当にです私はビルドしているモジュールのためのちょうど砂糖。 –

+0

ありがとうゲッターのために働く。 2番目の 'except'を' except AttributeError'に変更する必要があります。私はセッターを仕掛けたと思う。最終的な実装で編集された質問 –

関連する問題