Python: у каждого экземпляра должен быть свой суперкласс

В Python у меня есть экземпляры такого класса, как MyClass('name1'), MyClass('name2') и так далее.

Я хочу сделать так, чтобы у каждого экземпляра был свой суперкласс, т.е. MyClass('name1') быть примером Name1MyClass а также MyClass('name2') быть примером Name2MyClass, Name1MyClass а также Name2MyClass будут динамически генерируемые подклассы MyClass, Я не могу понять, как это сделать, потому что кажется, что Python всегда делает все, что возвращается из __new__ экземпляр этого класса. Мне тоже не понятно, как это сделать в метаклассе.

Причина, по которой я хочу это сделать, заключается в том, что я хочу определить __doc__ Строки документов на экземплярах. Но похоже что help полностью игнорирует __doc__ в случаях; это только смотрит на классы. Таким образом, чтобы поместить разные строки документации в каждый экземпляр, мне нужно, чтобы каждый экземпляр имел свой собственный класс.

1 ответ

Решение

Я могу ошибаться, но я не думаю, что вы хотите метакласс здесь. __metaclass__Они используются при создании класса, а не при вызове класса для создания нового экземпляра класса (или чего-то еще).

Вот ответ, используя __new__ без метакласса. Это выглядит немного странно, но, похоже, работает:

_sentinel = Ellipsis
class MyClass(object):
    def __new__(cls, name):
        if name is _sentinel:
            return object.__new__(cls)
        else:
            instance = type(name + cls.__name__, (MyClass,), {})(_sentinel)
            # Initialization goes here.
            return instance

print type(MyClass('name1'))
print type(MyClass('name2'))

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


Другой вариант - создать фабрику классов:

class MyClass(object):
    pass

def class_factory(name):
    new_cls = type(name + MyClass.__name__, (MyClass,), {})
    return new_cls() # Or pass whatever you want in here...

print type(class_factory('name1'))
print type(class_factory('name2'))

Наконец, вы могли бы даже создать не__new__ метод класса:

class MyClass(object):
    @classmethod
    def class_factory(cls, name):
        new_cls = type(name + cls.__name__, (cls,), {})
        return new_cls() # Or pass whatever you want in here...

print type(MyClass.class_factory('name1'))
print type(MyClass.class_factory('name2'))
Другие вопросы по тегам