LINUX.ORG.RU

[Python] Множественное наследование

 


0

2

Здравствуй ЛОР,

class A(object):
    def pr(self):
        print "A"

class B(object):
    def pr(self):
        print "B"

class C(A, B):
    def pr(self):
        super(C, self).pr()

if __name__ == '__main__':
    c = C()
    c.pr()

Как вызвать все функции pr у классов родителей? И почему вышеприведённый код этого не делает?

Ответ на: комментарий от mikki

Хорошая идея, можно даже verbosity в декораторе менять, но вот не понимаю твою реализацию. Можешь налабать хотя бы на псевдокоде? Пока не могу придумать красивое решение.

true_admin ★★★★★
()
Ответ на: комментарий от Deleted

если на столько часто приходится ходить в родительский метод, который чайлд переопределил, значит не все гладко в архитектуре

Вот один конкретный пример. Каждый потомок может добавить что-то к данным шаблона. Выглядит примерно так:

class base
{
    function template_data()
    {
        return array(); 
    }
}

...

class system extends base
{
    function template_data()
    {
        return array_merge(parent::template_data(), array(
            'me' => bors()->user(),
            'time' => time(),
            'client' => bors()->client(),
        )); 
    } 
}

...

class system extends base
{
    function template_data()
    {
        return array_merge(parent::template_data(), array(
            'items' => $this->items(),
            'query' => bors()->server()->request('q'),
        )); 
    } 
}

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

KRoN73 ★★★★★
()
Ответ на: комментарий от true_admin

С помощью декоратора нужно задавать log level всех объектов данного класса, я правильно понял?

Тогда можно сделать, допустим, так:

class logme(object):

    def __init__(self, log_level):
        self.log_level = log_level

    def _wrap_init(self, f):
        def _wrap(obj, *args, **kwargs):
            obj.log_level = self.log_level
            return f(obj, *args, **kwargs)
        return _wrap
    
    def __call__(self, cls):
        cls.__init__ = self._wrap_init(cls.__init__)
        return cls

# Тогда

@logme(13)
class A(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b


>>> a = A(1,2)
>>> a
<__main__.A object at 0x02C38A50>
>>> a.log_level
13

Я должен сказать, что даже в достаточно больших системах мне не приходилось делать фильтрацию логов для отдельных классов, - фильтрации на уровне модуля (из расчета «один logger на один» модуль всегда хватало.

shylent
()
Ответ на: комментарий от KRoN73

Это называется примесь, что по сути является частным случаем мульти наследования. Можно сказать это единственный вменяемый случай использования мультинаследования, но он имеет кучу ограничений.

Deleted
()
Ответ на: комментарий от shylent

не-не-не, там декоратор на методе был а не на всём классе :). На классе легко, можно даже без всяких декораторов выставлять self.verbosity. Но с декоратором как-то аккуратнее код, хотя это и лишняя сущность(лично я за аккуратность, зачем экономить талант? :)).

мне не приходилось делать фильтрацию логов для отдельных классов

И мне :). Но у меня щас есть наработки различные, я хочу их довести до ума, вот и заморочился вопросом. Интересно попытаться реализовать, а применять ли на практике это другой вопрос.

(ниже буду чудовищные вещи, слабонервным не читать)

Вообще, я бы сделал так: «парсил» бы байткод и вырезал все вызовы логгирования которые ниже определённого уровня. К сожалению модуль inspect оставляет временные файлы, зараза. А так задача решаемая. Хотя, наверно, для такого лучше бы иметь препроцессор... Но мнение Гвидо по поводу препроцессоров питона мы знаем :)

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

не-не-не, там декоратор на методе был а не на всём классе :). На классе легко, можно даже без всяких декораторов выставлять self.verbosity

Какая проблема с декоратором на метод? Всё почти то же самое, разница только в объёмах - адресно нужно трейсить метод или весь клас сразу

mikki
()
Ответ на: комментарий от true_admin

А, понятно. Я видел, что декоратор стоял на __init__, но мне показалось, что конечная цель - фильтровать на уровне класса без явных присваиваний в __init__ или где-то там еще.

Ну а если на метод декоратор делать, то там все будет намного проще (см. метод _wrap_init из предыдущего поста).

В отношении отрезания вызовов и т.п. Все это, конечно, интересно, но на боевой системе я бы все-таки просто поднял log-level с DEBUG на другой какой-нибудь, и все. Не стоит забывать, также, что в logging из стандартной библиотеки конфигурация иерархическая, т.е. вполне возможен вариант, когда один logger/handler в иерархии пропускает сообщение DEBUG, т.к. у него уровень логирования, допустим INFO, а другой его обрабатывает.

shylent
()
Ответ на: комментарий от shylent

Да, согласен. Поэтому думаю не дать ли каждому объекту свой экземпляр logger со своими опциями :). В общем, тут я уже теоретизирую, сильно большой огород городить не хочется.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

>Поэтому думаю не дать ли каждому объекту свой экземпляр logger со своими опциями :)

Как раз на днях завёл «индивидуальный логгинг». У каждого объекта теперь может быть свойство/метод logger_class, по которому создаётся нужный logger(). Так что: $this->logger()->debug('Тут какая-то фигня!');

KRoN73 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.