Python - Как определить атрибуты, не затронутые __getattr__? - PullRequest
4 голосов
/ 19 августа 2011

Я довольно новичок в Python.В последнее время в программировании на PHP я привык к творческому использованию «магических» методов __get и __set.Они вызывались только тогда, когда общедоступная переменная класса отсутствовала.

Я пытаюсь повторить то же поведение в Python, но, похоже, терпит неудачу.Поскольку, похоже, не существует способа на самом деле определить переменные класса способом C ++ / PHP, когда я пытаюсь использовать переменные внутри своего класса (то есть через себя), он вызывает __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 ]

1 голос
/ 19 августа 2011

__getattr__ вызывается только тогда, когда Python не может найти атрибут в самом экземпляре или в любом из его базовых классов.Простое решение - добавить Document и Filename к классу, чтобы он был найден.

class ApplicationSettings(object):
    Document = None
    Filename = None
    RootXml = '<?xml version="1.0"?><Settings></Settings>'
    ...
0 голосов
/ 26 ноября 2011

Очевидно, что если я проверю имя атрибута в __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)
0 голосов
/ 19 августа 2011

Я бы использовал Свойства .Использование декоратора @property делает его еще приятнее1008 *.

0 голосов
/ 19 августа 2011

Здесь вам действительно нужен дескриптор . Зацеплять __getattr__ и __setattr__ подобным образом не очень рекомендуется.

...