我有这个:
class MySession:
def __init__(self, session):
session['my-data'] = {} # my data is here
self._session = session
def __getattr__(self, name):
return self._session['my-data'][name]
def __setattr__(self, name, value):
my_data = self._session['my-data']
my_data[name] = value
self._session['my-data'] = my_data
obj = MySession({})
obj.x = 3
基本上我想用对象属性访问来封装对会话(子)字典的访问。但我不能这样做,因为这会导致无限递归,我猜是因为这样做:
self._session = session
调用setattr,后者又调用getattr,后者又调用getattr等
如何在实现getattr / setattr的类中预初始化一些(普通)属性?
答案 0 :(得分:2)
仅对普通属性字典中不存在的属性调用__getattr__
方法。然而,__setattr__
被无条件地称为(它的镜像真的是__getattribute__
而不是__getattr__
)。如果您可以在_session
中正确设置__init__
属性,则无需担心其他方法中的任何内容。
要添加属性而不进行任何递归,请使用super(MySession, self).__setattr__
调用从object
继承的方法的版本(您应该始终从Python 2中的object
继承到使你的类成为一个新式的类,在Python 3中,它是默认的)。您也可以直接致电object.__setattr__
,但如果您最终使用多重继承,则使用super
会更好。
class MySession(object):
def __init__(self, session):
session['my-data'] = {}
super(MySession, self).__setattr__("_session", session) # avoid our __setattr__
def __getattr__(self, name):
return self._session['my-data'][name] # this doesn't recurse if _session exists
def __setattr__(self, name, value):
my_data = self._session['my-data']
my_data[name] = value
self._session['my-data'] = my_data
答案 1 :(得分:1)
您可以先初始化并稍后更改setter getters:
def __init__(self, session):
session['my-data'] = {}
self._session = session
self.__setattr__ = self._setattr
self.__getattr__ = self._getattr
假设self._setattr
和self._getattr
当然是实施的:)