Уведомления

Группа в Telegram: @pythonsu

#1 Авг. 30, 2018 22:42:08

Levitanus
Зарегистрирован: 2018-05-01
Сообщения: 46
Репутация: +  0  -
Профиль   Отправить e-mail  

как лучше добавить кучу дескрипторов в класс?

Есть шаблонные свойства, необходимость прописи которых в __init__ потомков явно, или через super()
хотелось бы избежать.
Сначала подумал про декоратор класса вида

 from functools import wraps
class Prop:
    _objects = list()
    def __init__(self, name, func):
        self._name = name
        self._func = func
        cls = self.__class__
        if not hasattr(cls, '_objects'):
            cls._objects = list()
    def __get__(self, obj, cls):
        if obj is None:
            return self
        print(f'{self._name} is doing wrap')
        return self._func(obj)
    def store_obj(self, obj):
        print(obj)
        self.__class__._objects.append(obj)
    def do_something(self):
        for obj in self.__class__._objects:
            obj.do_something()
class Prop1(Prop):
    def __init__(self):
        super().__init__('prop1', self._func)
    def _func(self, obj):
        print(self._name)
class Prop2(Prop):
    def __init__(self):
        super().__init__('prop2', self._func)
    def _func(self, obj):
        print(self._name)
def has_1(cls):
    cls.prop1 = Prop1()
    orig_init = cls.__init__
    @wraps(orig_init)
    def wrapper(self, *args, **kwargs):
        cls.prop1.store_obj(self)
        return orig_init(self, *args, **kwargs)
    cls.__init__ = wrapper
    return cls
def has_2(cls):
    cls.prop2 = Prop2()
    orig_init = cls.__init__
    @wraps(orig_init)
    def __init(self, *args, **kwargs):
        cls.prop2.store_obj(self)
        return orig_init(self, *args, **kwargs)
    cls.__init__ = __init
    return cls
@has_1
class A:
    _count = int()
    def __init__(self):
        self.idx = A._count
        A._count += 1
        print(f'A.__init__({self.idx})')
    def do_something(self):
        print(f'A({self.idx}) is doing_something')
@has_2
class B:
    _count = int()
    def __init__(self):
        self.idx = B._count
        B._count += 1
        print(f'B.__init__({self.idx})')
    def do_something(self):
        print(f'B({self.idx}) is doing_something')
@has_1
@has_2
class C:
    _count = int()
    def __init__(self):
        self.idx = C._count
        C._count += 1
        print(f'C.__init__({self.idx})')
    def do_something(self):
        print(f'C({self.idx}) is doing_something')
a1 = A()
a1.prop1
a2 = A()
A.prop1.do_something()
b = B()
b.prop2
c = C()
c.prop1
c.prop2
вывод:
 <__main__.A object at 0x00C2A150>
A.__init__(0)
prop1 is doing wrap
prop1
<__main__.A object at 0x00C2A170>
A.__init__(1)
A(0) is doing_something
A(1) is doing_something
<__main__.B object at 0x00C2A250>
B.__init__(0)
prop2 is doing wrap
prop2
<__main__.C object at 0x02EABC10>
<__main__.C object at 0x02EABC10>
C.__init__(0)
prop1 is doing wrap
prop1
prop2 is doing wrap
prop2

Но, почитал StackOverflow, где говорили, что это ай-яй-яй, и лучше пишите метаклассы в таких случаях.

Сейчас заделал метакласс:
 class KspNativeControlMeta(WidgetMeta):
    objects_count = int()
    objects = list()
    def __new__(self, cls, bases, dct):
        # if kWidget not in bases:
        #     raise TypeError(f'has to be subclass of {kWidget}')
        cls = super().__new__(self, cls, bases, dct)
        if '__init__' in dct.keys():
            f = cls.__init__
        else:
            f = None
        ParentTuple = Optional[Union[kWidget, kMainWindow]]
        cls.x = ControlPar('x', cls, kArrInt, kParIntVar, int, 1,
                           set_control_par, get_control_par,
                           CONTROL_PAR_POS_X)
        @wraps(f)
        def init_wrapper(obj, *args, name: Optional[str]=None,
                         parent: ParentTuple=None,
                         x: Optional[int]=None, y: Optional[int]=None,
                         width: Optional[int]=None,
                         height: Optional[int]=None,
                         **kwargs):
            kWidget.__init__(obj, parent=parent, x=x, y=y,
                             width=width, height=height)
            obj._id = KspNativeControlMeta.objects_count
            if name is None:
                name = f'control{obj._id}'
            obj._name = name
            KspNativeControlMeta.objects.append(obj)
            KspNativeControlMeta.objects_count += 1
            try:
                obj.var = cls._var_type(name=name)
            except AttributeError:
                raise AttributeError(
                    'class has to contain attribute "_var_type" which is' +
                    f'subclass of {KspVar}')
            cls.id = ControlId(obj)
            cls.x._init_control(obj, x)
            if f:
                f(*args, **kwargs)
            return
        cls.__init__ = init_wrapper
        return cls
И вот эти строчки появились, потому что kWidget.__init__ вызывался дважды при пустом __init__ потомка:
 if '__init__' in dct.keys():
    f = cls.__init__
else:
    f = None
#....
if f:
    f(*args, **kwargs)
return
И, я так понимаю, что если потомок вызовет super, То проблема сохранится.
Я, в целом, понимаю, в чем проблема. Но вот что с ней делать – не знаю.

Отредактировано Levitanus (Авг. 30, 2018 22:44:09)

Офлайн

#2 Авг. 30, 2018 23:44:24

Levitanus
Зарегистрирован: 2018-05-01
Сообщения: 46
Репутация: +  0  -
Профиль   Отправить e-mail  

как лучше добавить кучу дескрипторов в класс?

а оказалось все так просто )

 class KspNativeControlMeta(WidgetMeta):
    objects_count = int()
    objects = list()
    def __new__(self, cls, bases, dct):
        cls = super().__new__(self, cls, bases, dct)
        cls.x = ControlPar('x', cls, kArrInt, kParIntVar, int, 1,
                           set_control_par, get_control_par,
                           CONTROL_PAR_POS_X)
        return cls
    ParentTuple = Optional[Union[kWidget, kMainWindow]]
    def __call__(cls, *args, name: Optional[str]=None,
                 parent: ParentTuple=None,
                 x: Optional[int]=None, y: Optional[int]=None,
                 width: Optional[int]=None,
                 height: Optional[int]=None,
                 **kwargs):
        obj = super().__call__(*args, parent=parent,
                               x=x, y=y,
                               width=width,
                               height=height, **kwargs)
        obj._id = KspNativeControlMeta.objects_count
        if name is None:
            name = f'control{obj._id}'
        obj._name = name
        KspNativeControlMeta.objects.append(obj)
        KspNativeControlMeta.objects_count += 1
        try:
            obj.var = cls._var_type(name=name)
        except AttributeError:
            raise AttributeError(
                'class has to contain attribute "_var_type" which is' +
                f'subclass of {KspVar}')
        cls.id = ControlId(obj)
        cls.x._init_control(obj, x)
        return obj

Офлайн

#3 Сен. 2, 2018 18:34:44

JamesSot
Зарегистрирован: 2018-06-07
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

как лучше добавить кучу дескрипторов в класс?

Транспортная компания Догрузов предоставляет услуги в сфере грузоперевозок в <a href=https://dogruzov.ru/perevozki-moskva-piter/>перевозка груза москва питер</a>
Наша компания имеет собственный автопарк, а так же договора с надежными, проверенными собственниками транспорта. Благодаря наработанным схемам

Офлайн

#4 Сен. 2, 2018 19:25:06

JamesSot
Зарегистрирован: 2018-06-07
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

как лучше добавить кучу дескрипторов в класс?

Транспортная компания Догрузов предоставляет услуги в сфере грузоперевозок в <a href=https://dogruzov.ru/perevozki-moskva-piter/>доставка груза до санкт-петербурга</a>
Наша компания имеет собственный автопарк, а так же договора с надежными, проверенными собственниками транспорта. Благодаря наработанным схемам

Офлайн

#5 Сен. 2, 2018 20:26:32

JamesSot
Зарегистрирован: 2018-06-07
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

как лучше добавить кучу дескрипторов в класс?

Транспортная компания Догрузов предоставляет услуги в сфере грузоперевозок в <a href=https://dogruzov.ru/poputnyj-gruz-iz-moskvy/>доставка попутного груза по россии</a>
Наша компания имеет собственный автопарк, а так же договора с надежными, проверенными собственниками транспорта. Благодаря наработанным схемам

Офлайн

#6 Сен. 2, 2018 21:28:39

JamesSot
Зарегистрирован: 2018-06-07
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

как лучше добавить кучу дескрипторов в класс?

Транспортная компания Догрузов предоставляет услуги в сфере грузоперевозок в <a href=https://dogruzov.ru/poputnyj-gruz-iz-moskvy/>попутный груз до москвы</a>
Наша компания имеет собственный автопарк, а так же договора с надежными, проверенными собственниками транспорта. Благодаря наработанным схемам

Офлайн

#7 Сен. 2, 2018 22:31:16

JamesSot
Зарегистрирован: 2018-06-07
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

как лучше добавить кучу дескрипторов в класс?

Транспортная компания Догрузов предоставляет услуги в сфере грузоперевозок в <a href=https://dogruzov.ru/>транспортная компания сборных грузов</a>
Наша компания имеет собственный автопарк, а так же договора с надежными, проверенными собственниками транспорта. Благодаря наработанным схемам

Офлайн

#8 Сен. 2, 2018 23:34:46

JamesSot
Зарегистрирован: 2018-06-07
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

как лучше добавить кучу дескрипторов в класс?

Транспортная компания Догрузов предоставляет услуги в сфере грузоперевозок в <a href=https://dogruzov.ru/>транспортная компания по перевозке грузов</a>
Наша компания имеет собственный автопарк, а так же договора с надежными, проверенными собственниками транспорта. Благодаря наработанным схемам

Офлайн

#9 Сен. 3, 2018 00:30:03

JamesSot
Зарегистрирован: 2018-06-07
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

как лучше добавить кучу дескрипторов в класс?

Транспортная компания Догрузов предоставляет услуги в сфере грузоперевозок в <a href=https://dogruzov.ru/perevozki-moskva-piter/>доставка с москвы в санкт-петербурге</a>
Наша компания имеет собственный автопарк, а так же договора с надежными, проверенными собственниками транспорта. Благодаря наработанным схемам

Офлайн

#10 Сен. 3, 2018 01:17:23

JamesSot
Зарегистрирован: 2018-06-07
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

как лучше добавить кучу дескрипторов в класс?

Транспортная компания Догрузов предоставляет услуги в сфере грузоперевозок в <a href=https://dogruzov.ru/perevozki-moskva-piter/>перевезти груз из москвы в спб</a>
Наша компания имеет собственный автопарк, а так же договора с надежными, проверенными собственниками транспорта. Благодаря наработанным схемам

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version