Задать вопрос
@shdprogrammer

Как перегрузить __getattribute__ класса через декоратор в Python?

Доброго всем времени суток. Подскажите, есть ли возможность в Python 2.6 перегрузить метод класса __getattribute__ через декоратор? Насколько я понимаю, декоратор класса, представляющий из себя класс, возвращает не оборачиваемый класс, а уже обернутый класс, и пробуя перегрузить метод, я описываю метод декоратора, а не перегружаю метод оборачиваемого класса.

Заранее спасибо.
  • Вопрос задан
  • 2693 просмотра
Подписаться 2 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 2
Tark
@Tark
Pyramid'альный мир
А чего именно вы хотите достичь? Чтобы можно было... что? Вы часто и помногу переопределяете функцию __getattribute__ и вам хочется сократить код? Тогда как вариант...

from functools import wraps


def wrap(f):
    def tmp(self, name):
        # print name
        if name == 'test':
            return 'some test'
        elif name == 'another':
            return 'another test'
        else:
            return f.__call__(object, name)
    return tmp


class Some(object):
    def __init__(self):
        self.some_value = 10

    @wrap
    def __getattribute__(self, name):
        if name == 'test1':
            return 'test string'
        return object.__getattribute__(self, name)

value = Some()
print value.test
print value.another
print value.test1


... выведет:
some test
another test
test string


ВАЖНОЕ УТОЧНЕНИЕ: я пришёл в Питон, когда уже была версия 2.7.2 и с ранними версиями не работал.
----------------------

Ответили уже, как вижу. А я дописал декоратор так, чтобы оно работало, лол.

# encoding: utf-8


def wrap(f):
    def tmp(self, name):
        arg, lang = name.split('_')
        try:
            return object.__getattribute__(self, name)
        except AttributeError:
            return object.__getattribute__(self, arg)
    return tmp


class Some(object):
    def __init__(self):
        self.language = 'Language'
        self.language_ru = u'Язык'

    @wrap
    def __getattribute__(self, name):
        return object.__getattribute__(self, name)

value = Some()
print value.language_ru
print value.language_ch
Ответ написан
@shdprogrammer Автор вопроса
Да, извиняюсь, надо было наверное привести полную задачу, а не ее часть. Есть сайт на django. Нужно перевести на несколько языков его базу. Решил попробовать сделать это через декоратор модели. Декоратор добавляет поля с префиксом языка, это сделано. Теперь требуется в зависимости от установленного языка обращаться к стандартному полю, или к полю с префиксом. Для этого хотел перегрузить __getattribute__ модели. Хотел сделать это в том же декораторе. Плюс кастомный менеджер что бы перехватывать обращения и направлять их к нужным полям.

Декоратор:
class AAA(object):

    def __init__(self, *fields):

        self.fields = fields

    def __call__(self, cls):
        meta = cls._meta

        for field_name in self.fields:

            try:
                field = meta.get_field_by_name(field_name)[0]
            except IndexError:
                raise Exception('Field not found in %s?' % cls)

            # костыль
            params = {'verbose_name': getattr(field, 'verbose_name', None),
                      'blank': getattr(field, 'blank', None),
                      'null': getattr(field, 'null', None),
                      'choices': getattr(field, 'choices', None),
                      'default': getattr(field, 'default', None),
                      'max_length': getattr(field, 'max_length', None),
                      'help_text': getattr(field, 'help_text', None)}
            params = {k: v for k, v in params.iteritems() if v}

            for l in dict(settings.LANGUAGES).iterkeys():

                if l == settings.DEFAULT_LANGUAGE:
                    continue

                fname = '%s_%s' % (l, field_name)
                ftype = field.__class__.__name__
                cls.add_to_class(fname, getattr(models, ftype)(**params))

        cls.add_to_class('objects', InternationalizedManager())

        return cls


Собственно решение не претендует на крутость, может это вообще костыль или велосипед и есть более простые вещи сделать это, делалось для начала на попробовать и посмотреть что из этого выйдет.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы