Что такое правильная реализация шаблона проектирования декоратора в Python? - PullRequest
0 голосов
/ 11 декабря 2018

У меня есть несколько подклассов, которые имеют некоторые параллельные атрибуты, и я хочу использовать шаблон декоратора, чтобы я мог просто построить другой граф с простым синтаксисом isinstance.Я сослался на этот пост .

Мой тестовый код (Py27) выглядит так:

import inspect 

class Cls_Base(object):
    def __init__(self, n):
        self.number = n
    def __str__(self):
        return '{}, {}'.format(self.number,self.__class__.__name__)

class Ext_c1(Cls_Base):
    def __init__(self):
        self.pos=self.number+3
    def __str__(self):
        return '{}, {}'.format(self.pos,self.__class__.__name__)

class Ext_c2(Cls_Base):
    def __init__(self):
        pass
    def __str__(self):
        return '{}, {}'.format(self.number+1,self.__class__.__name__)

class Cls_Decorator(Cls_Base):
    def __new__(cls, decoratee, c):
        cls_name=c if inspect.isclass(c) else globals()[c]
        cls = type(cls_name.__name__,
                   (cls_name, decoratee.__class__),
                   decoratee.__dict__)
        return object.__new__(cls) 

base=Cls_Base(1)
c1=Cls_Decorator(base,Ext_c1)
c1_2=Cls_Decorator(c1,Ext_c2)
c2=Cls_Decorator(base,Ext_c2)

При рассмотрении значения и метода c1, c1_2, c2,результаты получаются следующими:

>>> base.__dict__
{'number': 1}
>>> c1.__dict__
{}
>>> c2.__dict__
{}
>>> c1_2.__dict__
{}
>>> str(c1)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "test_cls.py", line 17, in __str__
    return '{}, {}'.format(self.pos,self.__class__.__name__)
AttributeError: 'Ext_c1' object has no attribute 'pos'
>>> str(c2)
'2, Ext_c2'
>>> str(base)
'1, Cls_Base'
>>> str(c1_2)
'2, Ext_c2'
>>> c1.__init__()
>>> str(c1)
'4, Ext_c1'
>>> c1.__dict__()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: 'dict' object is not callable
>>> c1.__dict__
{'pos': 4}

Видите, перегруженные и унаследованные методы работают хорошо.Но декоратор не может инициировать dict класса из-за того, что инициатор не вызывается до выделения нового пространства.Что я мог сделать, чтобы избежать явного использования __init__() вне класса?Или есть какой-то более изящный способ выполнять эквивалентные задания?

ДОПОЛНИТЕЛЬНЫЙ ВОПРОС : использование inspect.getmro может вызвать другую проблему, так как два Ext_c1 ниже не совпадают.

>>> inspect.getmro(type(c1))
(<class '__main__.Ext_c1'>, <class '__main__.Ext_c1'>, 
<class '__main__.Cls_Base'>, <type 'object'>)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...