Python - 如何定义不受__getattr__影响的属性?

时间:2011-08-18 23:55:37

标签: python xml ironpython getattr

我对Python很新。在最近对很多PHP进行编程时,我习惯于使用__get__set“魔术”方法。只有当班级的公共变量不存在时才会调用它们。

我正在尝试在Python中复制相同的行为,但似乎失败了。鉴于似乎没有办法以C ++ / PHP方式实际定义类变量,当我尝试在我的类中通常使用变量时(即通过self),它最终调用__getattr__

如何定义我不希望受__getattr__影响的班级属性?

我正在尝试做的一些示例代码如下所示,我希望self.Documentself.Filename不要调用__getattr__

感谢您的帮助!

class ApplicationSettings(object):
    RootXml = '<?xml version="1.0"?><Settings></Settings>'

    def __init__(self):
        self.Document = XmlDocument()
        self.Document.LoadXml(RootXml)

    def Load(self, filename):
        self.Filename = filename
        self.Document.Load(filename)

    def Save(self, **kwargs):
        # Check if the filename property is present
        if 'filename' in kwargs:
            self.Filename = kwargs['filename']

        self.Document.Save(self.Filename)

    def __getattr__(self, attr):
        return self.Document.Item['Settings'][attr].InnerText

    def __setattr__(self, attr, value):
        if attr in self.Document.Item['Settings']:
            # If the setting is already in the XML tree then simply change its value
            self.Document.Item['Settings'][attr].InnerText = value
        else:
            # Setting is not in the XML tree, create a new element and add it
            element = self.Document.CreateElement(attr)
            element.InnerText = value

            self.Document.Item['Settings'].AppendChild(element)

4 个答案:

答案 0 :(得分:1)

仅当Python无法在实例本身或其任何基类中找到该属性时,才会调用

__getattr__。简单的解决方案是将DocumentFilename添加到类中,以便找到它。

class ApplicationSettings(object):
    Document = None
    Filename = None
    RootXml = '<?xml version="1.0"?><Settings></Settings>'
    ...

答案 1 :(得分:0)

这里你真正需要的是descriptor。像这样挂钩__getattr____setattr__并不是真正推荐的方法。

答案 2 :(得分:0)

我会使用Properties。使用@property装饰器使它看起来更好。

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

然后,您可以访问C.x,它会自动调用x的getter,并在您分配给C.x时自动调用x的setter。

答案 3 :(得分:0)

显然,如果我在__setattr__中检查属性名称,那么我可以调用对象的__setattr__来获取我想要正常使用的属性。这感觉很糟糕,但很有效。

    def __setattr__(self, attr, value):
        # Check for attributes we want to store normally
        if attr == 'Document' or attr == 'Filename':
            object.__setattr__(self, attr, value)
        # If the setting is already in the XML tree then simply change its value
        elif attr in self.Document.Item['Settings']:
            self.Document.Item['Settings'][attr].InnerText = value
        # Setting is not in the XML tree, create a new element and add it
        else:
            element = self.Document.CreateElement(attr)
            element.InnerText = value

            self.Document.Item['Settings'].AppendChild(element)