gpt4 book ai didi

python - 在运行时覆盖 __setattr__

转载 作者:IT老高 更新时间:2023-10-28 21:18:39 35 4
gpt4 key购买 nike

我正在尝试覆盖 Python 类的 __setattr__ 方法,因为我想在每次实例属性更改其值时调用另一个函数。但是,我不希望在 __init__ 方法中出现这种行为,因为在此初始化期间,我设置了一些稍后将使用的属性:

到目前为止,我有这个解决方案,没有在运行时覆盖 __setattr__:

class Foo(object):
def __init__(self, a, host):
object.__setattr__(self, 'a', a)
object.__setattr__(self, 'b', b)
result = self.process(a)
for key, value in result.items():
object.__setattr__(self, key, value)

def __setattr__(self, name, value):
print(self.b) # Call to a function using self.b
object.__setattr__(self, name, value)

但是,我想避免这些 object.__setattr__(...) 并在 __init__ 方法的末尾覆盖 __setattr__ :

class Foo(object):
def __init__(self, a, b):
self.a = a
self.b = b
result = self.process(a)
for key, value in result.items():
setattr(self, key, value)
# override self.__setattr__ here

def aux(self, name, value):
print(self.b)
object.__setattr__(self, name, value)

我试过 self.__dict__['__setitem__'] = self.auxobject.__setitem__['__setitem__'] = self.aux,但没有一个这些尝试是有效果的。我已阅读 this section of the data model reference ,但看起来自己的 __setattr__ 的赋值有点棘手。

怎么可能在 __init__ 的末尾覆盖 __setattr__,或者至少有一个 Python 的解决方案,其中 __setattr__ 在正常方式只在构造函数中?

最佳答案

不幸的是,没有办法“在 init 之后覆盖”python 特殊方法;作为该查找如何工作的副作用。问题的症结在于python实际上并没有查看实例;除了得到它的类;在它开始查找特殊方法之前;因此无法让对象的状态影响查找的方法。

如果您不喜欢 __init__ 中的特殊行为,您可以重构代码以将特殊知识放入 __setattr__ 中。比如:

class Foo(object):
__initialized = False
def __init__(self, a, b):
try:
self.a = a
self.b = b
# ...
finally:
self.__initialized = True

def __setattr__(self, attr, value):
if self.__initialzed:
print(self.b)
super(Foo, self).__setattr__(attr, value)

编辑:实际上,有一种方法可以更改查找哪个特殊方法,只要在初始化后更改其类。这种方法会让您远离元类的杂草,因此无需进一步解释,如下所示:

class AssignableSetattr(type):
def __new__(mcls, name, bases, attrs):
def __setattr__(self, attr, value):
object.__setattr__(self, attr, value)

init_attrs = dict(attrs)
init_attrs['__setattr__'] = __setattr__

init_cls = super(AssignableSetattr, mcls).__new__(mcls, name, bases, init_attrs)

real_cls = super(AssignableSetattr, mcls).__new__(mcls, name, (init_cls,), attrs)
init_cls.__real_cls = real_cls

return init_cls

def __call__(cls, *args, **kwargs):
self = super(AssignableSetattr, cls).__call__(*args, **kwargs)
print "Created", self
real_cls = cls.__real_cls
self.__class__ = real_cls
return self


class Foo(object):
__metaclass__ = AssignableSetattr

def __init__(self, a, b):
self.a = a
self.b = b
for key, value in process(a).items():
setattr(self, key, value)

def __setattr__(self, attr, value):
frob(self.b)
super(Foo, self).__setattr__(attr, value)


def process(a):
print "processing"
return {'c': 3 * a}


def frob(x):
print "frobbing", x


myfoo = Foo(1, 2)
myfoo.d = myfoo.c + 1

关于python - 在运行时覆盖 __setattr__,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16426141/

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