18

我编写了以下包装类。我想定义__setattr__它以将所有属性重定向到包装类。但是,这会阻止我初始化包装类。有什么优雅的方法来解决这个问题吗?

class Wrapper:
    def __init__(self, value):
        # How to use the default '__setattr__' inside '__init__'?
        self.value = value

    def __setattr__(self, name, value):
        setattr(self.value, name, value)
4

4 回答 4

18

您正在捕获所有分配,这会阻止构造函数分配self.value. 您可以使用self.__dict__来访问实例字典。尝试:

class Wrapper:
    def __init__(self, value):
        self.__dict__['value'] = value

    def __setattr__(self, name, value):
        setattr(self.value, name, value)

另一种使用方式object.__setattr__

class Wrapper(object):
    def __init__(self, value):
        object.__setattr__(self, 'value', value)

    def __setattr__(self, name, value):
        setattr(self.value, name, value)
于 2012-10-21T15:05:16.710 回答
11

此处介绍了一种在初始化后禁用__setattr__until 而不更改方法中的self.value = value语法的__init__方法。简而言之,在对象中嵌入初始化知识,并在方法中使用它。对于您的:__setattr__Wrapper

class Wrapper:
    __initialized = False
    def __init__(self, value):
        self.value = value
        self.__initialized = True

    def __setattr__(self, name, value):
        if self.__initialized:
            # your __setattr__ implementation here
        else:
            object.__setattr__(self, name, value)
于 2014-06-20T19:00:01.070 回答
0

__getattr__被覆盖::

class Wrapper:
    def __init__(self,wrapped):
        self.__dict__['wrapped'] = wrapped
    def __setattr__(self,name,value):
        setattr(self.__dict__['wrapped'],name,value)
    def __getattr__(self,name):
        return getattr(self.__dict__['wrapped'],name)


class A:
    def __init__(self,a):
        self.a = a

wa = Wrapper(A(3))
#wa.a == wa.wrapped.a == 3
于 2016-06-03T13:54:16.673 回答
0

正如其他答案中所建议的,一种想法是直接访问对象字典以绕过setattr解析。

为了便于阅读,我建议以下内容:

  def __init__(self,wrapped1, wrapped2):
       vars(self).update(dict(
          _wrapped1=wrapped1,
          _wrapped2=wrapped2,
        ))

使用vars是可选的,但我发现它比直接访问更好self.__dict__,并且内联dict()表示法允许将所有实例变量初始化分组在一个可见块中,并且样板代码开销最小。

于 2019-11-03T01:48:46.857 回答