Как стать автором
Обновить

Комментарии 4

Похоже на выполнение домашнего задания.
Классы задача 2: а что вернет d = DictAttr(); d['pop'] = 1; print d.pop?
Классы задача 4: зачем тут метаклассы?
можно просто
class Reg(object):
__instances = []
def __init__(self):
self.__instances.append(self)

1. вернет метод, потому что унаследовано от dict. Сама затея делать так — плохая и даже на хабре было пару статей с реализацией подобного словаря. И в них тоже были грабли.
2. я изначально сделал так, но не смог сделать итератор вида:
for i in Reg:

Заметьте, не такие:
for i in Reg.__iter__()
for i in Reg()
for i in Reg._instances

а именно указанный. Если подскажете как, буду благодарен.
насчет второго, извиняюсь, не заметил подставы — действительно интересно.
И вот тут, в случае неудачи, в дело вступает грязный хак. Я так и не смог придумать, как исключить возможность рекурсии, потому что необходимо проверить наличие атрибута get_KEY, которое происходит через вызов __getattr__ объекта

А как на счет такой реализации?
class XDictAttr(dict):
    """
    >>> class X(XDictAttr):
    ...     def get_foo(self):
    ...         return 5
    ...     def get_bar(self):
    ...         return 12
    ...     def get_get_z(self):
    ...         return 42
    ...     def get_get_get_get_get_foo(self):
    ...         return 4242

    >>> x = X({'one': 1, 'two': 2, 'three': 3})
    >>> x
    X: {'one': 1, 'three': 3, 'two': 2}
    >>> x['one']
    1
    >>> x.three
    3
    >>> x.bar
    12
    >>> x['foo']
    5
    >>> x.get('foo', 'missing')
    5
    >>> x.get('bzz', 'missing')
    'missing'
    >>> x.get_bar()
    12
    >>> x.get_foz()
    Traceback (most recent call last):
    ...
    AttributeError
    >>> x.get_get_z()
    42
    >>> x.get('get_z')
    42
    >>> x.get_z
    42
    >>> x.get_get_get_get_get_foo()
    4242
    >>> x.get_get_get_get_foo
    4242
    >>> x.get('get_get_get_get_foo')
    4242
    """

    def __repr__(self):
        return '%s: %s' % (self.__class__.__name__, super(XDictAttr, self).__repr__())

    def _get_attr_with_prefix(self, attr):
        if hasattr(self, 'get_%s' % attr):
            return getattr(self, 'get_%s' % attr)()
        else:
            raise AttributeError

    def __getattr__(self, attr):
        try:
            return self._get_attr_with_prefix(attr)
        except AttributeError:
            try:
                return super(XDictAttr, self).__getitem__(attr)
            except KeyError:
                raise AttributeError

    def __getitem__(self, key):
        try:
            return self._get_attr_with_prefix(key)
        except AttributeError:
            return super(XDictAttr, self).__getitem__(key)

    def get(self, key, default=None):
        try:
            return self._get_attr_with_prefix(key)
        except AttributeError:
            return super(XDictAttr, self).get(key, default)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории