私は、カスタム クラス階層でのサブ要素属性へのアクセスにすべて気を配ろうとしています。私の空想は、これを行うために記述子をうまく使用できるという点で機能します。私はさらに凝って、スペースを節約するためにスロットRefHolder
を使用するクラス (以下のテストケースに表示)を作成したいと考えています。
ただし、スロットを使用しようとすると、RuntimeError: maximum recursion depth exceeded
私はすでにこれに対する既存の解決策を調べてみたことに注意してください.最もよく一致するのはこれです:
https://stackoverflow.com/a/19566973/1671693
以下のテストケースでこれを試しましたが、まだランタイム エラーが発生します。
テストケースで、コメント行がその直下の行の代わりに使用され、__slots__
から削除されたRefHolder
場合、テストケースはパスすることに注意してください。
助言がありますか?さらに、コストがかかると思われるすべての属性アクセスに対してオブジェクトを作成していますが、同じ動作を実現するより効率的な方法について何か提案はありますか? ありがとう!
import unittest
class RefHolder():
__slots__ = ['__obj', 'get_value']
def __init__(self, obj, get_value=False):
self.__dict__['__obj'] = obj
self.__dict__['get_value']=get_value
def get_sub(self, name):
#attr = self.__dict__['__obj'].find_by_name(name)
attr = self.__dict__['__obj'].__get__(self, RefHolder).find_by_name(name)
if attr is None:
raise AttributeError("Can't find field {}".format(name))
return attr
def __getattr__(self, name):
attr = self.get_sub(name)
#if self.__dict__['get_value']:
if self.__dict__['get_value'].__get__(self, RefHolder):
return attr.Value
else:
return attr
def __setattr__(self, name, value):
attr = self.get_sub(name)
#if self.__dict__['get_value']:
if self.__dict__['get_value'].__get__(self, RefHolder):
attr.Value = value
else:
raise AttributeError("{} is read only in this context".format(name))
class ContainerAccess():
__slots__ = ['get_value']
def __init__(self, get_value=False):
self.get_value = get_value
def __get__(self, obj, objtype=None):
if obj is None:
return self
return RefHolder(obj, self.get_value)
def __set__(self, obj, value):
raise AttributeError("Read Only attribute".format(value))
class PropVal():
def __init__(self, val):
self.Value = val
@property
def Value(self):
return self._value
@Value.setter
def Value(self, value):
self._value = value
class T():
get = ContainerAccess()
getv = ContainerAccess(get_value=True)
def __init__(self):
self.store = {}
self._value = 0
def find_by_name(self, name):
return self.store.get(name)
class T2(T):
pass
class TestDesc(unittest.TestCase):
def test_it(self):
t = T()
t2 = T2()
t.store['my_val'] = PropVal(5)
t.store['my_val2'] = PropVal(6)
t2.store['my_val'] = PropVal(1)
self.assertEqual(t.get.my_val.Value, 5)
self.assertEqual(t.get.my_val2.Value, 6)
self.assertEqual(t2.get.my_val.Value, 1)
t.get.my_val.Value = 6
self.assertEqual(t.get.my_val.Value, 6)
with self.assertRaises(AttributeError):
t.get.blah.Value = 6
#self.assertEqual(t.get.my_other_val.Value, None)
self.assertEqual(t.getv.my_val, 6)
t.getv.my_val = 7
self.assertEqual(t.getv.my_val, 7)
with self.assertRaises(AttributeError):
t.get.my_val = 7