问题
I've written the following wrapper class. I want to define __setattr__
such that it redirects all attributes to the wrapped class. However, this prevents me from initializing the wrapper class. Any elegant way to fix this?
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)
回答1:
You are catching all assignments, which prevents the constructor from assigning self.value
. You can use self.__dict__
to access the instance dictionary. Try:
class Wrapper:
def __init__(self, value):
self.__dict__['value'] = value
def __setattr__(self, name, value):
setattr(self.value, name, value)
Another way using object.__setattr__
:
class Wrapper(object):
def __init__(self, value):
object.__setattr__(self, 'value', value)
def __setattr__(self, name, value):
setattr(self.value, name, value)
回答2:
A way to disable the __setattr__
until after initialization without changing the self.value = value
syntax in the __init__
method is covered here. In short, embed knowledge of initialization in the object and use it in the __setattr__
method. For your 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)
回答3:
With __getattr__
overridden as well::
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
回答4:
As suggested in other answers, one idea is to directly access the object dictionary to bypass setattr
resolution.
For something easy to read, I suggest the following:
def __init__(self,wrapped1, wrapped2):
vars(self).update(dict(
_wrapped1=wrapped1,
_wrapped2=wrapped2,
))
Using vars is optional, but I find it nicer than directly accessing self.__dict__
, and the inline dict()
notation allows for grouping all instance variable initialization in a visible block with minimum boilerplate code overhead.
来源:https://stackoverflow.com/questions/12998926/clean-way-to-disable-setattr-until-after-initialization