Класс Python, унаследованный от временного класса
Я застрял, когда я пытаюсь выяснить следующее 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 ответ
Для ответа нам сначала не нужен класс FormMeta. Представьте себе определение формы следующим образом:
class Form(with_metaclass(meta=type, base=BaseForm)):
# ...
with_metaclass
звонок только возвращается meta("NewBase", (base,), {})
что в данном случае просто type("NewBase", (base,), {})
, который создает новый класс с именем NewBase
, который является производным от base
(BaseForm
в этом случае), без дополнительных методов. Вы можете прочитать об этом в документации по типу.
FormMeta
метакласс в этом случае ничего не делает. Наследует type
(именно поэтому это мета класс), а затем просто передает полученные данные type
, плюс некоторые печатные заявления. Так что по сути это то же самое, что и выше. Вы можете прочитать больше о метаклассах здесь.