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)
4 ответа:
__getattr__
вызывается только тогда, когда Python не может найти атрибут в самом экземпляре или в любом из его базовых классов. Простое решение состоит в том, чтобы добавитьDocument
иFilename
в класс, чтобы он был найден.class ApplicationSettings(object): Document = None Filename = None RootXml = '<?xml version="1.0"?><Settings></Settings>' ...
Я бы использовал свойства . Использование декоратора
@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, а также автоматически вызовет сеттер для x, когда вы назначаетеC.x
.
Очевидно, если я проверяю имя атрибута в
__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)