实现getattr / setattr

时间:2015-12-01 16:43:49

标签: python

我有这个:

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的类中预初始化一些(普通)属性?

2 个答案:

答案 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._setattrself._getattr当然是实施的:)