gpt4 book ai didi

使用自定义 __getattr__ 和 __setattr__ 的 Python 深度复制

转载 作者:行者123 更新时间:2023-12-02 04:03:39 24 4
gpt4 key购买 nike

我实现了一个类,它可以区分一组固定的实例属性(我们称之为元属性)和任意一组其他实例属性。

它有自定义的__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

这工作正常,所有元属性都直接进入实例的 __dict__ ,而所有其他属性都进入 params 字典:

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}}

除了当我尝试深度复制我的对象时,它会做一些奇怪的事情:

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__

最佳答案

这会导致递归查找(记住obj2不是通过__init__初始化的)

return self.params[key]

你应该这样做

return super().__getattribute__('params')[key]

关于使用自定义 __getattr__ 和 __setattr__ 的 Python 深度复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40583131/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com