4

我对 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

4 回答 4

1

__getattr__仅当 Python 在实例本身或其任何基类中找不到属性时才调用。简单的解决方案是将Document和添加Filename到类中,以便找到它。

class ApplicationSettings(object):
    Document = None
    Filename = None
    RootXml = '<?xml version="1.0"?><Settings></Settings>'
    ...
于 2011-08-19T00:47:41.117 回答
0

你真正需要的是一个描述符。挂钩之__getattr____setattr__的并不是真正推荐的方法。

于 2011-08-19T01:37:18.053 回答
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,并在你分配给时自动调用 x 的 setter C.x

于 2011-08-19T16:09:30.123 回答
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)
于 2011-11-26T00:15:09.070 回答