Можно ли заставить методы метакласса участвовать в разрешении методов?

Рассмотрим этот пример:

class Meta(type):
    def method(*_, **__):
        print('Meta')


class A(object):
    __metaclass__ = Meta


class B(object):
    @classmethod
    def method(*_, **__):
        print('B')


class C(A, B):
    pass


C.method() # prints 'B'

Здесь у нас есть класс A, у которого есть метод method, определенный в его метаклассе Meta. И у нас есть класс B, который также имеет метод method, но определенный как метод класса.

Класс C, который наследуется как от A, так и от B, в результате имеет method от класса B.

Но если бы A определял method как метод класса, C унаследовал method от A.

Я хочу найти способ сделать возможным Meta.method участие в наследовании, как если бы это был метод класса класса, который использует этот метакласс. Можно как-то?


person Gill Bates    schedule 06.04.2016    source источник
comment
C также имеет Meta в качестве своего метакласса, как и любой подкласс A. Должен ли C вести себя так, как будто у него есть собственное определение method, как вы хотите, чтобы A вел себя?   -  person user2357112 supports Monica    schedule 06.04.2016


Ответы (1)


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

Если вам нужен метод для участия в MRO, поместите его в сам класс. Метакласс может сделать это:

class Meta(type):
    def __new__(mcls, name, bases, body):
        cls = super(Meta, mcls).__new__(mcls, name, bases, body)
        if not hasattr(cls, 'method'):
            @classmethod
            def method(*_, **__):
                print('Meta')
            cls.method = method
        return cls

Это прикрепляет метод к вновь созданному классу, только если такого метода еще нет; это позволяет вашему классу (или любым подклассам) переопределять метод, предоставленный метаклассом, и предотвращает получение того же самого любым подклассом, где он может быть унаследован.

person Martijn Pieters    schedule 06.04.2016