Класс Python, унаследованный от временного класса - PullRequest
0 голосов
/ 20 ноября 2018

Я застрял, когда я пытался выяснить следующее codes:

def with_metaclass(meta, base=object):
    print("[2]")
    return meta("NewBase", (base,), {})

class BaseForm(object):
    def __init__(self, fields, prefix=''):
       print(self.__class__)

    def say(self):
        print("BaseForm")


class FormMeta(type):
    def __init__(cls, name, bases, attrs):
        print("[3]: {!r}, {!r}, {!r}, {!r}, {!r}".format(cls, name, type(cls), bases, attrs))
        type.__init__(cls, name, bases, attrs)

    def __call__(cls, *args, **kwargs):
        print("[4]: {!r}, {!r}".format(cls, type(cls)))
        return type.__call__(cls, *args, **kwargs)

print("[1]")
class Form(with_metaclass(FormMeta, BaseForm)):
    print("[5]")
    def __init__(self):
        NewBase.__init__(self)
        print("[6]: {!r}, {!r}".format(self, type(self)))


# confused position
print(Form.__bases__)

# Form is based on NewBase, however, there is no NewBase
print(dir())

Вот вывод кода:

[1]
[2]
[3]: <class '__main__.NewBase'>, 'NewBase', <class '__main__.FormMeta'>, (<class '__main__.BaseForm'>,), {}
[5]
[3]: <class '__main__.Form'>, 'Form', <class '__main__.FormMeta'>, (<class '__main__.NewBase'>,), {'__module__': '__main__', '__qualname__': 'Form', '__init__': <function Form.__init__ at 0x7f6ad4d76f28>}
(<class '__main__.NewBase'>,)
['BaseForm', 'Form', 'FormMeta', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'with_metaclass']

Так же, как я прокомментировал, Form основано на NewBase, однако в основном модуле нет класса NewBase.Класс, его базовый класс недоступен, это ошибка?Но интересно, что Form все еще может вызывать метод, который исходит от родителя его родителя.

1 Ответ

0 голосов
/ 20 ноября 2018

Ради ответа нам сначала не нужен класс FormMeta.Представьте себе определение формы следующим образом:

class Form(with_metaclass(meta=type, base=BaseForm)):
    # ...

вызов with_metaclass просто возвращает meta("NewBase", (base,), {}), что в данном случае равно type("NewBase", (base,), {}), что создает новый класс с именем NewBase, которыйполучено из base (BaseForm в данном случае), без дополнительных методов.Вы можете прочитать об этом в документации типа .

Метакласс FormMeta в этом случае ничего не делает.Он наследует type (именно поэтому это мета-класс), а затем просто передает полученные данные в type плюс некоторые операторы печати.Так что по сути это то же самое, что и выше.Вы можете прочитать больше о метаклассах здесь .

...