Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 10, 2013 07:59:08

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

Можно ли как-то получить список всех вложенных классов?

Имеем такой код:

    class Base(object):
        class ChildA(object):
            def register(self, parent):
                pass
     
        class ChildB(object):
            def register(self, parent):
                pass
     
        def __init__(self):
            # ???        

хотелось бы в конструкторе класса Base получить список всех его вложенных классов, создать экземпляры и вызвать метод register.

Отредактировано andrews (Июнь 10, 2013 07:59:45)

Офлайн

#2 Июнь 10, 2013 08:23:03

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Можно ли как-то получить список всех вложенных классов?

# -*- coding:utf-8 -*-
class Meta(type):
    def __new__(cls, name, base, dct):
        dct.update(class_list=list())
        for v in dct.values():
            if hasattr(v, "register"):
                dct["class_list"].append(v)
        return super(Meta, cls).__new__(cls, name, base, dct)
class BaseChild(object):
    def register(self):
        print "register ", self, "parent", self.parent
class Base(object):
    __metaclass__ = Meta
    class ChildA(BaseChild): pass
    class ChildB(BaseChild): pass
    def __init__(self):
        for cls in self.class_list:
            obj = cls()
            obj.parent = self
            setattr(self, cls.__name__.lower(), obj)
            obj.register()
a = Base()



Офлайн

#3 Июнь 10, 2013 10:07:28

buddha
От:
Зарегистрирован: 2012-03-02
Сообщения: 422
Репутация: +  15  -
Профиль   Отправить e-mail  

Можно ли как-то получить список всех вложенных классов?

Я вот так сделал:

import inspect
 
 
class Base(object):
 
    def __init__(self):
        self.childs = inspect.getmembers(self, inspect.isclass)  # получил все классы
        self.childs = [child for child in self.childs if not child[0].startswith('__')]  # убрал из них лишнее
          
        for child in self.childs:
            cls = child[1]
            inst = cls()
            inst.register('some_parent')
 
    class ChildA(object):
        def register(self, parent):
            pass
  
    class ChildB(object):
        def register(self, parent):
            pass
 
b = Base()

Отредактировано buddha (Июнь 10, 2013 10:08:16)

Офлайн

#4 Июнь 10, 2013 10:17:59

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

Можно ли как-то получить список всех вложенных классов?

Благодарю за ответы. Предполагал, что это можно сделать через метаклассы, но не знал как их применить для данной задачи. Думаю остановиться на варианте, предложенном FishHook

Офлайн

#5 Июнь 10, 2013 22:14:48

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

Можно ли как-то получить список всех вложенных классов?

FishHook
В чем целесообразность делать это через метаклассы?
Я бы наверно предложил над-класс с property class_list

Офлайн

#6 Июнь 11, 2013 05:57:08

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Можно ли как-то получить список всех вложенных классов?

o7412369815963, так Вы предложИте, там и посмотрим, что получится целесообразней



Офлайн

#7 Июнь 11, 2013 22:35:48

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

Можно ли как-то получить список всех вложенных классов?

FishHook
o7412369815963, так Вы предложИте, там и посмотрим, что получится целесообразней
Ну, например так - то же самое, но метакласс заменил на класс:
class Meta(object):
    @property
    def class_list(self):
        for v in map(lambda k:getattr(self, k), dir(self)):
            if hasattr(v, "register"):
                yield v
class BaseChild(object):
    def register(self):
        print "register ", self, "parent", self.parent
class Base(Meta):
    class ChildA(BaseChild): pass
    class ChildB(BaseChild): pass
    def __init__(self):
        for cls in self.class_list:
            obj = cls()
            obj.parent = self
            setattr(self, cls.__name__.lower(), obj)
            obj.register()
a = Base()
Обычно метаклассы используют там где “штатно” не выходит. Конечно на метаклассах тоже вариант, и можно было-бы пойти дальше - заюзать какие-нибудь C-extention, но зачем?

Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version