Переопределение __getattr__ для поддержки динамических вложенных атрибутов

Каков наилучший подход, если вы хотите динамически создавать вложенные атрибуты и ссылаться на них?

Я писал простой Клиент Flickr и хотел, чтобы он как можно точнее соответствовал документированному API, фактически не определяя каждый метод. Например, чтобы сделать запрос к Flickr flickr.people.getInfo API-метод :

flickr = Client()
data = flickr.people.getInfo(user_id='xxx')

В этом случае flickr.people.getInfo напрямую сопоставляется с соответствующим методом в их документация по API. При вызове люди и getInfo создаются по мере их поиска,тогда правильный запрос определяется путем к getInfo , то есть people.getInfo . Я использовал следующий подход:

class Attr(object):
    def __init__(self, client, name, parent):
        self._client = client
        self._name = name
        self._parent = parent

    def __getattr__(self, name):
        attr = Attr(self._client, name, self)
        setattr(self, name, attr)
        return attr

    def _get_path(self, path=None):
        if path:
            path = '.'.join((self._name, path))
        else:
            path = self._name
        if isinstance(self._parent, Attr):
            return self._parent._get_path(path)
        return path

    def __call__(self, *args, **kwargs):
        return self._client.execute_method(self._get_path(), *args, **kwargs)

class Client(object):
    def __getattr__(self, name):
        attr = Attr(self, name, None)
        setattr(self, name, attr)
        return attr

    def execute_method(self, method, *args, **kwargs):
        print method, args, kwargs

Это работает, но мне любопытно, можно ли улучшить мой подход к назначению / поиску вложенных атрибутов или есть какие-то ошибки, которые поджидают меня, без моего ведома. В частности, мне любопытно, есть ли лучший способ выяснить «путь» к заданному атрибуту. Например, если я вызываю Client (). Xyz () , x , y , z , не существуют и будут создается один за другим (поскольку __ getattr __ просматривает за раз только один атрибут). К моменту вызова z мне нужно понять, что путь к z равен x.y.z .

15
задан zeekay 28 June 2011 в 16:51
поделиться