0
私は、インスタンス属性の固定セット(メタ属性と呼ぶ)と他のインスタンス属性の任意のセットを区別できるクラスを実装しました。カスタム__getattr__と__setattr__を使ったPythonディープコピー
それはカスタム__getattr__
と__setattr__
あります
class MyClass(object):
def __init__(self, meta1, meta2, **other_attr):
super(MyClass, self).__setattr__('meta1', meta1)
super(MyClass, self).__setattr__('meta2', meta2)
super(MyClass, self).__setattr__('params', {})
self.params = {key: other_attr[key] for key in other_attr}
# this is called when default lookup finds nothing
def __getattr__(self, key):
print('__getattr__({})'.format(key))
try:
return self.params[key]
except KeyError:
raise AttributeError(key)
# this is called always
def __setattr__(self, key, value):
print('__setattr__({}, {})'.format(key, value))
if key in self.__dict__:
super(MyClass, self).__setattr__(key, value)
else:
self.params[key] = value
これは正常に動作し、他のすべての属性がparams
辞書に行っている間、すべてのメタ属性は、インスタンスの__dict__
に直接移動:
obj1 = MyClass(meta1 = 'foo', meta2 = 'bar', x=1, y=2, z=3)
obj1.w = 4
print(obj1.__dict__)
出力:
__setattr__(params, {'y': 2, 'x': 1, 'z': 3})
__setattr__(w, 4)
{'meta1': 'foo', 'meta2': 'bar', 'params': {'y': 2, 'x': 1, 'z': 3, 'w': 4}}
を除き、私は私のオブジェクトをdeepcopy
しようとすると、それは奇妙な何かを行います。
import copy
obj1 = MyClass(meta1='foo', meta2='bar', x=1, y=2, z=3)
obj2 = copy.deepcopy(obj1)
出力:最後に
__setattr__(params, {'y': 2, 'x': 1, 'z': 3})
__getattr__(__deepcopy__)
__getattr__(__getnewargs__)
__getattr__(__getstate__)
__getattr__(__setstate__)
__getattr__(params)
__getattr__(params)
__getattr__(params)
__getattr__(params)
__getattr__(params)
__getattr__(params)
__getattr__(params)
__getattr__(params)
...
and then it calls __getattr__ about a hundred more times
をそれはがコピーを作成しますが、なぜんそれは__getattr__
に非常に多くの呼び出しを行いますか?これは、再帰検索を引き起こしている
おかげで、行う必要があります。しかし、なぜそれが*無限*再帰を引き起こさないのですが、ある時点で停止しますか? – spiderface
@spiderface、 'RuntimeError:Pythonオブジェクトを呼び出す際に最大再帰深度を超過しました。 'おそらくあなたは若干異なる例外ハンドラを持つバージョンを試しました –
それは変です。また、私は '__getattribute__'の値を返す必要がないことも知っていました。単にそれを呼び出して' return self.params [key] 'を返すだけで十分です。 – spiderface