Python - 如何定义不受 __getattr__ 影响的属性?
我对 Python 还很陌生。最近,在进行大量 PHP 编程时,我习惯了一些创造性地使用 __get 和 __set“神奇”方法。仅当类的公共变量不存在时才会调用它们。
我试图在 Python 中复制相同的行为,但似乎失败了。鉴于似乎没有办法以 C++/PHP 方式实际定义类变量,当我尝试在类中正常使用变量(即通过 self)时,它最终会调用 __getattr__ !
如何定义我不希望受到 __getattr__
影响的类属性?
下面是我想要做的一些示例代码,我在其中希望 self.Document 和 self.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)
I'm fairly new to Python. In programming a lot of PHP recently I got used to some creative use of __get
and __set
"magic" methods. These were only called when a public variable of the class wasn't present.
I'm trying to replicate the same behavior in Python, but seem to be failing miserably. Given there doesn't seem to be a way to actually define class variables in a C++/PHP way, when I try to use variables normally within my class (i.e. via self) it ends up calling __getattr__
!
How do I define attributes of my class that I don't want affected by __getattr__
?
Some sample code of what I'm trying to do is below, where I'd want self.Document
and self.Filename
NOT to invoke __getattr__
.
Thanks for the help!
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
仅当 Python 在实例本身或其任何基类中找不到该属性时,才会调用 __getattr__ 。简单的解决方案是将
Document
和Filename
添加到类中,以便找到它。__getattr__
is only invoked when Python cannot find the attribute in the instance itself or in any of its base classes. The simple solution is to addDocument
andFilename
to the class so it is found.这里你真正需要的是一个描述符。像这样挂钩 __getattr__ 和 __setattr__ 并不是真正推荐的方法。
What you really need here is a descriptor. Hooking
__getattr__
and__setattr__
like that is not really recommended method.我会使用属性。使用@property装饰器使它看起来更好。
然后您可以访问
Cx
,它会自动调用x的getter,并在您分配给Cx
时自动调用x的setter。I would use Properties. Using the
@property
decorator makes it looks even nicer.You can then access
C.x
and it will automatically call the getter for x, and automatically call the setter for x when you assign toC.x
.显然,如果我检查 __setattr__ 中的属性名称,我就可以调用对象的 __setattr__ 来获取我想要正常使用的属性。这感觉很古怪,但很有效。
Apparently if I check for the attribute name in
__setattr__
I can then call object's__setattr__
for the attributes I want to use normally. This feels pretty hoaky, but works.