Класс декоратора Python для преобразования методов в элементы словаря - PullRequest
1 голос
/ 20 июля 2010

Интересно, есть ли разумный простой способ разрешить работу этого кода (с незначительными изменениями).

class Info(object):
    @attr("Version")
    def version(self):
        return 3

info = Info()
assert info.version == 3
assert info["Version"] == 3

В идеале, код также должен выполнять некоторое кэширование / запоминание, например, использовать lazyатрибуты, но я надеюсь выяснить это сам.

Дополнительная информация:

Причина, по которой я хочу предоставить два интерфейса для доступа к одной и той же информации, заключается в следующем.

Я хотел бы иметь класс, похожий на диктовку, который использует ленивые ключи.Например, info["Version"] должен вызывать и кэшировать другой метод и прозрачно возвращать результат.Я не думаю, что это работает только с диктовками, поэтому мне нужно создавать новые методы.Сами по себе методы тоже не годятся, потому что есть некоторые атрибуты, которые проще определить с помощью чистого словарного синтаксиса.

Вероятно, в любом случае это не лучшая идея ...

Ответы [ 2 ]

1 голос
/ 20 июля 2010

Если имя атрибута (version) всегда является строчной версией клавиши dict ("Version"), то вы можете установить ее следующим образом:

class Info(object):
    @property
    def version(self):
        return 3
    def __getitem__(self,key):
        if hasattr(self,key.lower()):
            return getattr(self,key.lower())

Если вы хотите, чтобы диктЕсли ключ будет произвольным, то это все еще возможно, хотя и более сложно:

def attrcls(cls):
    cls._attrdict={}
    for methodname in cls.__dict__:
        method=cls.__dict__[methodname]
        if hasattr(method,'_attr'):
            cls._attrdict[getattr(method,'_attr')]=methodname
    return cls

def attr(key):
    def wrapper(func):
        class Property(object):
            def __get__(self,inst,instcls):
                return func(inst)
            def __init__(self):
                self._attr=key
        return Property()
    return wrapper

@attrcls
class Info(object):
    @attr("Version")
    def version(self):
        return 3
    def __getitem__(self,key):
        if key in self._attrdict:
            return getattr(self,self._attrdict[key])

Я предполагаю, что главный вопрос в том, хороший ли это интерфейс?Зачем предоставлять два синтаксиса (с двумя разными именами) для одной и той же вещи?

0 голосов
/ 20 июля 2010

Не тривиально.Вы можете использовать метакласс для обнаружения декорированных методов и соответственно обернуть __*attr__() и __*item__().

...