Python 实现getattr/setattr的类中的普通属性

Python 实现getattr/setattr的类中的普通属性,python,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, nam

我有这个:

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
基本上,我想用对象属性access封装对会话(子)字典的访问。但我不能这样做,因为这会导致无限递归,我猜是因为这样做:

self._session = session
调用setattr,setattr调用getattr,getattr调用getattr,等等


如何在实现getattr/setattr的类中预初始化某些(普通)属性?

您可以先初始化,然后更改setter-getter:

def __init__(self, session):
    session['my-data'] = {}
    self._session = session
    self.__setattr__ = self._setattr
    self.__getattr__ = self._getattr

假设
self.\u setattr
self.\u getattr
当然是实现的:)

只对普通属性字典中不存在的属性调用
\u getattr\u
方法
\uuuuu setattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。如果可以在
\uuu init\uuuu
中正确设置
\u会话
属性,则不必担心其他方法中的任何问题

要添加属性而不运行任何递归,请使用
super(MySession,self)。\uuuuu setattr\uuuuu
调用从
object
继承的方法的版本(在Python 2中,您应该始终从
object
继承,使您的类成为一个新样式的类,在Python 3中,它是默认的)。您也可以直接调用
对象。\uuuu setattr\uuuu
,但如果最终使用多重继承,则使用
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

这会导致相同的无限递归:self.session再次调用getattrGreat,谢谢。关于setattr的实现:我知道这很尴尬,但这与django中会话的工作方式有关:设置子键不会更新会话。这是一种常见的django gotcha<代码>类型错误:super()至少接受1个参数(给定0)
。我使用的是Python2.7Ah,我假设您使用的是Python3,因为您的类缺少
object
。在Python2中,您肯定希望这样做(或者无论您如何称呼它,
super
都无法工作)。您还需要为
super
调用提供参数,因为Python 2的版本不能像Python 3那样自动推断类。我已经更新了Python 2的答案,并将
\uuuu setattr\uuuu
实现恢复到您所说的方式。不幸的是,它不起作用_未使用getattr。这的确很奇怪。